Spring中Aop的实现

Spring中AOP的实现分为两种:

一、Java配置实现

1、通过注解定义拦截规则

2、通过方法路径定义拦截规则

二、XML配置实现

1、通过注解定义拦截规则

2、通过方法路径定义拦截规则


 一、Java配置实现

(1)Java配置实现,定义一个注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAction {
}

(2)定义Target,Target中有部分方法加有注解,凡是加有注解的方法都会被拦截下来,没加注解的方法则不受影响:

@Component
public class MyCalcultor {   
     @MyAction    
     public int add(int a, int b) {   
         System.out.println("add。。。");  
          return a + b;    }   

     public String sayHello(String name) {   
         return "hello " + name + " !";   
     }
}

(3)定义切面,切面包含两个部分:切点+增强(通知)分为五大类

*前置通知、通知在目标方法执行之前

*后置通知、通知在目标方法执行之后

*异常通知、通知在目标方法抛异常执行

*返回通知、通知在目标方法有返回值时执行

*环绕通知、包含了前面四种

@Component
@Aspect
public class LogAspect {   
     /**
       * @param point 参数是指连接点,从这个参数中,可以获取方法名方法参数等信息     
       * @Before注解表示这是一个前置通知,该通知会在目标方法执行之前执行    
       */  
    @Before("@annotation(MyAction)")    
    public void before(JoinPoint point) {        
    String name = point.getSignature().getName();        
    System.out.println(name + "方法开始执行了...");    
    }
}

(4)其他四种类型的通知

/** 
  * 这个类就是切面,该类中的内容包含两大块:切点+通知 
  * 
  * @Componet只是将该类注册到Spring容器中 
  * @Aspect表示该类是一个切面  
  */@Component
  @Aspect
  public class LogAspect {    
      /**     
       * @param point 参数是指连接点,从这个参数中,可以获取方法名方法参数等信息     
       * @Before注解表示这是一个前置通知,该通知会在目标方法执行之前执行     
       */    
@Before("@annotation(MyAction)")    
public void before(JoinPoint point) {        
    String name = point.getSignature().getName();        
    System.out.println(name + "方法开始执行了...");    
}    

/**     
* 这是一个后置通知,后置通知在目标方法执行结束后执行     
* @param point     
*/    
@After("@annotation(MyAction)"){ 
    System.out.println(point.getSignature().getName() + "方法执行结束了...");    
}    

/**     
* 这是一个返回通知,可以获取目标方法的返回值     
*     
* 方法中的参数名和注解中的参数名是对应的,参数值就是目标方法的返回值     
*     
* 需要注意返回值的类型,返回值的类型必须是参数的类或者子类     
*/    
@AfterReturning(value = "@annotation(MyAction)",returning = "result")    
public void returning(JoinPoint point,Object result) {
    System.out.println(point.getSignature().getName() + "方法的返回值是:" + result);    
}    

    /**     
    * 这是一个异常通知,该通知在方法执行抛出异常时执行     
    *     
    * 如果目标方法没有异常,则通知不会被触发     
    */    
@AfterThrowing(value = "@annotation(MyAction)",throwing = "e")    
     public void throwing(JoinPoint point,Exception e) {                                     System.out.println(">>>>>"+e.getMessage());    
}    
    /**     
    * 环绕通知是上面四种通知的集大成者,因为这个通知中包含了上面四种通知的功能    
    *     
    * @param pjp 这个参数类似于Method对象     
    * @return     
    */    
@Around("@annotation(MyAction)")    
public Object around(ProceedingJoinPoint pjp) {        
    //pjp.proceed() 就类似于method.invoke()        
    try {            
        //写在这个位置的,就是前置通知            
    Object proceed = pjp.proceed();            
        //写在这个位置的,就是后置通知           
         return proceed;       
     }catch (Throwable throwable) {            
    //写在这个位置的,就是异常通知            
        throwable.printStackTrace();        
    }        
        return null;    }
}

(5)可以通过如下方法简化切点的定义:

   /**     
    * 可以单独定义一个方法,专门用来定义切点,然后在其他方法中引用     
    */    
@Pointcut("@annotation(MyAction)")    
public void pointcut() {   

}

二、XML配置实现

(1)通过方法路径定义拦截规则,实际上只是切点的定义方式变了,其他的还是一样的。

 /**     
* 可以单独定义一个方法,专门用来定义切点,然后在其他方法中引用     
*  第一个* 表示目标方法的返回值,可以是任意类型,*表示任意类型     
*  第二个*表示类中的任意方法     
*  两个.表示方法的参数任意(可有可无,类型任意)     
*     
*  例如,想精确定位到add方法,步骤如下:     
*  execution(int com.itbaizhan.service.MyCalcultor.add(int,int))     
*/    
@Pointcut("execution(* com.itbaizhan.service.*.*(..))")    
public void pointcut() {  
  }

(2)使用表达式,可以较好的满足最小侵入式原则。

猜你喜欢

转载自blog.csdn.net/qq_38037950/article/details/83831240