(一)AOP术语:
连接点(JoinPoint)--- 使用:获取到切点的信息,包括传入参数
切点(poincut)---- 需要开启事务管理的方法
切面(Aspect)---- 切点和通知定义了切面的全部内容
(1)前置通知(Before):在目标方法被调用前通知
(2)后置通知(After):目标方法完成之后调用,不会关心方法的输出是什么
(3)返回通知(After-returning):目标成功执行之后调用通知
(4)异常通知(After-throwing):目标方法出现异常时候通知
(5)环绕通知(Around):把目标方法包裹起来,在方法执行前和调用之后执行自定义的行为
引入(Introduction)--允许我们向现有类添加新方法或属性
织入(Weaving)--把切面应用到目标对象并创建新的代理的过程
(二)spring借鉴了AspectJ的切面,以提供注解驱动的AOP。且spring只支持方法级别的连接点
——————Spring AOP只使用一些AspectJ提供的注解,没有使用AspectJ的处理功能
——————@AspectJ 采用注解的方式来配置使用 Spring AOP
AOP支持的AspectJ切入点指示符如下:
execution:用于匹配方法执行的连接点;
within:用于匹配指定类型的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;
AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。
实例 execution([返回类型] [所属类].[方法名]([参数])) * 代表返回任意类型 .. 代表任意参数
execution(* concert.Text.pweform(..))
execution(* concert.Text.pweform(..))&&within(concert.*) 仅concert包下的任意类被调用时
/**
* Spring 推荐写法 建立一个SystemArchitecture
* 用于定义 切点 Pointcut
*/
@Aspect
public class SystemArchitecture {
// web 层
@Pointcut("within(com.fostlin.controller..*)")
public void inWebLayer() {}
// service 层
@Pointcut("within(com.fostlin.service..*)")
public void inServiceLayer() {}
/**
* dao 层
*/
/*
@Pointcut("within(com.fostlin.dao..*)")
public void inDataAccessLayer() {}*/
// service 实现,注意这里指的是方法实现,其实通常也可以使用 bean(*ServiceImpl)
@Pointcut("execution(* com.fostlin..service.*.*(..))")
public void businessService() {}
/* // dao 实现
@Pointcut("execution(* com.fostlin.dao.*.*(..))")
public void dataAccessOperation() {}*/
}
接下来,我们要配置 Advice。
注意,实际写代码的时候,不要把所有的切面都揉在一个 class 中。
@Aspect
public class TestAdvice {
/**
* 执行之前
* @param jp 获取传入的参数
*/
@Before("com.fostlin.transaction.SystemArchitecture.businessService()")
public void beforeTest(JoinPoint jp){
System.out.println("方法执行前,打印入参:" + Arrays.toString(jp.getArgs()));
}
/**
* 执行之后
* @param retVal 返回值
*/
@AfterReturning(pointcut="com.fostlin.transaction.SystemArchitecture.inServiceLayer()",
returning="retVal")
public void afterReturningTest(Object retVal){
}
/**
* 异常返回
*/
@AfterThrowing(pointcut = "com.fostlin.transaction.SystemArchitecture.inServiceLayer()",
throwing = "ex")
public void afterThrowingTest(Exception ex){
}
/**
* 注意理解它和 @AfterReturning 之间的区别,这里会拦截正常返回和异常的情况
*/
@After("com.fostlin.transaction.SystemArchitecture.inServiceLayer()")
public void afterTest(){
// 通常就像 finally 块一样使用,用来释放资源。
// 无论正常返回还是异常退出,都会被拦截到
}
/**
* 环绕 相当于 Before与 AfterReturning的功能合并
* @param pjp
* @return
* @throws Throwable
*/
@Before("com.fostlin.transaction.SystemArchitecture.inServiceLayer()")
public Object beforeTest(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch 继续往下执行
Object retVal = pjp.proceed();
return retVal;
}
}