1. Spring中定义切面类
- 切面类 : 公共的代码
- @Aspect 声明一个切面类 ,spring会去 扫描 这些切面类 ,扫描切面类中的一些通知注解
- 通知类型:前置通知Before,后置通知 After等等,下面代码中对通知类型有详细体现,它表示在执行业务方法的何时(前/后/环绕)去切入公共点代码(切面类中的方法)
- 切入点表达式:用来拦截 (定位) 某一个 (某一些 ) 业务方法,下面的代码意味着在 执行 UserService对象的 saveUser方法之前 动态切入 beginTransaction 这个切面方法
execution(
modifiers-pattern? 拦截的方法的访问修饰符
ret-type-pattern 方法返回类型,必须指定
declaring-type-pattern? 拦截的方法所在的类
name-pattern(param-pattern) 拦截的方法以及方法的参数列表
throws-pattern? 方法声明的异常
)
@Before(“execution(*com.sky.spring_aop_execution.UserService.saveUser(…))”)
- 如何动态切入的:在解析切入点表达式的时候,如果切入点表达式拦截到了某一个类(UserService)中的方法(saveUser),那么从 IOC容器中 获取 到的就不再是原对象了,而是通过代理模式代理之后的代理对象,这样执行方法实际上是执行代理对象的方法,就会在执行目标对象方法的前后动态 切入 公共代码
@Component("aop") //添加到ioc容器
@Aspect //指定该类为一个切面类
public class TransactionAop {
//[前置通知] 在执行目标对象方法之前执行
@Before("execution(* com.sky.spring_aop_execution.UserService.saveUser(..))")
public void beginTransaction(){
System.out.println("【前置通知】");
}
//[后置通知] 在执行目标对象方法之后执行
@After("execution(* com.sky.spring_aop_execution.UserService.saveUser(..))")
public void commit(){
System.out.println("【后置通知】");
}
//[返回后通知] 在执行完目标对象结束后执行 ,在后置通知之后执行 . 出现异常 不执行
@AfterReturning("execution(* com.sky.spring_aop_execution.UserService.saveUser(..))")
public void afterRuturning(){
System.out.println("【返回后通知】");
}
//[异常通知] 在执行目标方法的时候出现异常后执行
@AfterThrowing("execution(* com.sky.spring_aop_execution.UserService.saveUser(..))")
public void afterThrowing(){
System.out.println("【异常后通知】");
}
//[环绕通知] 会环绕 目标方法执行
@Around("execution(* com.sky.spring_aop_execution.UserService.saveUser(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("【环绕前】");
//执行目标方法
pjp.proceed();
System.out.println("【环绕后】");
}
}
一句话总结springAop:把公共方法动态切入到某个业务方法中,由通知类型 决定(前置通知/后置通知)什么时候切入,拦截哪些方法由切入点表达式决定
2.注解方式实现spring声明式事务管理(粗粒度的事务控制)
- @Transactional:对指定的方法添加事务控制(一般是service层的业务方法)
- readOnly: 读写的事务,当修改数据时,设置为false。查询数据时,修改为true
- timeOut:事务执行的超时事务,-1表示不超时
- isolation:事务隔离级别(默认为读已提交READ_COMMITTED,其他的包括:可重复读REPEATABLE_READ,顺序读SERIALIZABLE)
- propagation:事务的传播行为
REQUIRES : 当前执行方法必须在事务环境下才能运行,如果调用该方法之前已经有了一个事务环境,就不会开启新的事务,如果调用该方法之前没有事务环境,就会开启一个新的事务环境
REQUIRES_NEW : 当前执行方法 必须 在事务环境下才能运行,调用该方法之前不管有没有事务环境,始终开启新的事务
SUPPORTS: 支持事务环境。如果当前方法没有事务环境,也可以运行 Never: 当前方法不能在事务环境下运行
@Transactional(
readOnly=false,
timeout=-1,
isolation=Isolation.DEFAULT,
propagation=Propagation.REQUIRED
)
public void saveUser(){
//调用dao层方法
userDao.saveUser();
}