AOP

基于注解的AOP

结构

 

 

 

动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)
 
cglib:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口
 
AspectJ:本质上是静态代理,将代理逻辑“织入”被代理的目标类编译得到的字节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解
 
 

准备

使用基于注解的AOP时,首先需要创建一个切面类
然后组件和切面类上都需要添加@Component等四个注解,此外,切面类上还需要添加@Aspect来将其标记为切面
在IOC配置文件中添加context:component-scan进行扫描
在配置文件中还需要添加<aop:aspectj-autoproxy>,来开启基于注解的aop功能
 
 

使用

在切面类中,编写具体的横切关注点,在切入点上添加注解来指定连接点的位置

@Before在执行前

@After相当于finally里面

@AfterReturning在正常执行后

@AfterThrowing相当于catch里面

@Around环绕通知,相当于前四个加起来

注解中必须有切入点表达式

表达式用来指定当前切入点作用于哪个类的那个函数上

@Before("execution(修饰符 返回值 全类名.方法名(参数类型))")

如:@Before("exection(public int com.darkpar.CalculatorImpl.add(int,int)))")

可以使用通配符进行代替,达到匹配多个函数或多个类的目的

如:@Before("exection(* com.darkpar.*.*(..)))")

被通知注解标记的类可以在参数列表添加JointPoint,可以返回连接点的信息

如:
@Before
public void beforeMethod(JoinPoint joinPoint){
  Signature signature = joinPoint.getSignature();
  Object[] args=joinPoint.getArgs();
  String name=signature.getName();
}

对于AfterReturning注解来说可以设置接受返回值的参数名

如:
@AfterReturning(value="pointCut()",returning="result")
public void afterReturningMethod(JoinPoint joinpoint,Object result){
  sout(result);
}

对于AfterThrowing注解来说可以设置接受异常的参数名

如:
@AfterThrowing(value="pointCut()",throwing="exception")
public void afterReturningMethod(JoinPoint joinpoint,Throwable exception){
  sout(exception);
}
 

声明切入点表达式来进行切入点重用

@Pointcut("exection(public int com.darkpar.CalculatorImpl.add(int,int)))")

public void pointCut(){}

 
后面的注解中可以使用这个声明的方法作为value,就能按这个连接点定位了
@Before("pointCut()")

并且其他的切面中也可以共享使用这个切入点

 
 

注意

被代理的对象无法通过IOC进行获取,只能通过接口类型来获取代理类的对象   

 
通知执行的顺序跟spring版本有关

5.3之前:

前置通知

目标操作

后置通知

返回或异常通知

5.3之后:

前置通知

目标操作

返回或异常通知

后置通知

 

环绕通知

和之前写的动态代理类似,自己进行函数的执行并返回结果

@Around("cutPoint")

public Object aroundMethod(ProceedJoinPoint joinPoint){

  Object result=null;

  try{

    BEFORE

    result=joinPoint.proceed();

    AFTERRETURNING

  }catch(Exception){

    AFTERTHROWING

  }finally{

    AFTER

  }

  return result;

}

切面的优先级

@Order注解可以使用在切面上

注解可以设置切面的优先级,int类型,数字越小优先级越高

 

基于XML的AOP

不常使用,以注解为主
在切面上不使用AOP相关的注解,在IOC配置文件中配置,
首先还是扫描组件
<context:component-scan base-package="com.darkpar.aop.xml"/>
然后进行aop:config标签的配置
<aop:config>
  <aop:pointcut id="pointCut" experssion="exection(* com.darkpar.*.*(..)))">
  <aop:aspect ref="loggerAspect" order="1"> 
    <aop:before method="beforeMethod" pointcut-ref="pointCut">
 
  </aop:aspect>
</aop:config>