学习了Spring之后,一直没有总结,总感觉差点东西,以下仅代表个人观点
1.Spring的理解
Spring是一对象的容器
2.Spring注入对象
2.1空参构造注入
<bean name="名称" class="注入对象全路径" scope="scope属性" Init-method="初始化方法" destroy-method="销毁方法">
</bean>
2.1.1scope属性
singleton(默认值):单例对象,在spring容器中智慧存在一个实例
prototype:多例原型,每次获得都重新创建(action要配置成多例)
request:web环境下,与request生命周期一致
session:web环境下,与session生命周期一致
2.1.2 生命周期
Init-method配置初始化方法,spring会在对象创建之后立即调用
destroy-method配置销毁方法,spring会在关闭销毁钱调用
2.2注解注入
开启注解扫描
<context:component-scan base-package="com.xxx.bean"/>
2.2.1注解创建对象(加载类上)
@Component("user")//通用
@Service("user")//service业务层
@Controller("user")//web层
@Repository("user")//仓库,dao层
2.2.2注解加入范围
@Scope(scopeName="prototype") //单例或多例
2.2.3注解注入属性
@Value("tom")//注入属性,建议加在set方法上
2.2.4注解注入对象
@Autowired//自动装配(问题:如果有多个同类对象,无法选择注入哪个)
@Qualifier("car2")//解决办法1在添加一个
@Resource(name="car2")//解决办法2使用手动注解
2.2.5注解初始化与销毁方法
@PostConstruct // 在构造后调用
@PreDestroy // 在销毁前调用,仅单例模式可用
3.Spring IOC&DI
IOC: Inverse Of Control 反转控制 将对象的创建权限交给Spring
DI: Dependency injection 依赖注入
实现IOC思想需要DI做支持:
注入方式:Set方法注入,构造方法注入,字段注入
注入类型:值类型注入(8大基本数据类型)、引用类型注入(将依赖对象注入)
4.Spring AOP
4.1AOP思想
面向切面编程,纵向重复,横向抽取
例子:过滤器、拦截器、动态代理
4.2 Spring AOP(动态代理,cglib)
1)动态代理(优先)
被代理对象必须实现接口,否则就不行
2)cglib代理(无法使用动态代理就用动态代理)
可以对任何类生成代理(原理:对目标对象进行集成代理,所以不能被final修饰)
总结:
1通过动态代理可以体现AOP思想,但是AOP并不仅仅指动态代理
2对目标对象中的方法进行增强
3为容器中管理的对象生成动态代理对象
4Spring封装了动态代理与cglib,我们只需要调用,可以对任何类进行代理增强
4.3 AOP名词(行话)
1)Joinpoint(连接点):目标对象中可以增强的方法
2)Pointcut(切入点):目标对象中已经增强的方法
3)Advice(通知/增强):用来增强目标对象的代码
4)Target(目标对象):被代理对象,就是目标对象
5)Weaving(织入):将通知(Advice)应用到切入点(Pointcut)的过程,生成代理对象的过程叫织入
6)Proxy(代理):将通知织入到目标对象后,形成代理对象
7)Aspect(切面):切入点+通知(增强后的内容)
4.4 Spring AOP到底如何用?
4.4.1xml配置
1 让spring帮生成代理对象,需要准备目标对象Target
<bean name="userService" class="com.tang.service.UserServiceImpl" />
2 给目标对象准备通知Advice
<bean name="myAdvice" class="com.tang.d_aop.MyAdvice" />
3 配置进行织入,将通知织入目标对象Weaving
Pointcut配置:
id:切点名称,取名任意
expression="" 切点覆盖范围(要增强谁?)
1) execution("public void com.tang.service.UserServiceImpl.save()") =>全称
2) execution("void com.tang.service.UserServiceImpl.save()") =>返回类型省略
3) execution("* com.tang.service.UserServiceImpl.save()") =>对返回值不要求
4) execution("* com.tang.service.UserServiceImpl.*()") =>对方法不要求
5) execution("* com.tang.service.UserServiceImpl.*(..)") =>对方法的参数不要求
6) execution("* com.tang.service.*ServiceImpl.*(..)") =>对service不要求
7) execution("* com.tang.service..*ServiceImpl.*(..)") =>对子包也扫描
<aop:config>
<aop:pointcut expression="execution(* com.tang.service.*ServiceImpl.*(..))" id="pc" />
<!-- 配置切面Aspect ref:通知对象的名称-->
<aop:aspect ref="myAdvice">
<!-- 前置通知 -->
<aop:before method="before" pointcut-ref="pc"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
<!-- 换绕通知 -->
<aop:around method="around" pointcut-ref="pc"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<!-- 后置通知 -->
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
4.4.2注解配置
1.在通知包class前写
@Aspect
2.抽取切点,在通知包类内写
@Pointcut(value="execution(* com.tang.service.*ServiceImpl.*(..))")
public void pc(){}
3.配置织入,将通知包内方法前赋值属性
// 前置通知
@Before(value="MyAdvice.pc()")
// 返回后后置通知(方法没有异常时调用)
@AfterReturning(value="execution(* com.tang.service.*ServiceImpl.*(..))")
// 环绕通知
@Around(value="execution(* com.tang.service.*ServiceImpl.*(..))")
// 异常拦截通知
@AfterThrowing(value="execution(* com.tang.service.*ServiceImpl.*(..))")
// 后置通知(无论如何都要调用)
@After(value="execution(* com.tang.service.*ServiceImpl.*(..))")
5.Spring整合Junit测试
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.xxx.User;
@RunWith(SpringJUnit4ClassRunner.class) // 注入JUnit
@ContextConfiguration("classpath:applicationContext.xml") // 注入容器
public class Demo {
@Resource(name="user")//将user对象注入u
private User u;
@Test
// 空参构造
public void testSpringJunit() throws Exception {
System.out.println(u);
}
}
6.Spring事务
6.1 事务
6.1.1事务并发问题
1)脏读
2)幻读
3)不可重复读
6.2.2事务隔离级别(解决并发问题)
1)1读未提交
2)2读已提交
3)4可重复读
4)8串行化
6.2 Spring事务管理
6.2.1接口
1)提供PlaformTransactionManager接口,针对不同平台实现不同实现类
DataSourceTransactionManager
HibernateTransactionManager
2)可选配置
事务隔离级别1 2 4 8
是否只读true(只读)false(可操作的)
事务的传播行为(解决业务方法之间平行调用时,事务处理方式问题)
PROPAGATION_REQUIRED 支持当前事务,如果不存在,就新建(默认)
PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
PROPAGATION_REQUIRES_NEW 必须开一个新的事务
PROPAGATION_NOT_SUPPORTED 如果有事务,就挂起事务,无事务执行
PROPAGATION_NEVER 永远不用事务
PROPAGATION_NESTED 如果有,就在开一个事务