spring03-aop

06-30 1211阅读

  • spring aop: 只能增强方法,,spring aop 底层是动态代理,,,动态代理的本质是生成一个子类,,重写这个方法,进行增强,,所以final修饰的类和方法,,或者是static静态方法,或者是private修饰的方法,都不能被继承,都会导致spring aop 失效

    spring03-aop
    (图片来源网络,侵删)
  • aspectJ aop: 能增强属性,类,静态方法,,等,是一个完整的,独立的,功能十分强大的aop解决方案,,是编译时增强,,性能也高于aop,,当然也支持运行时增强

    spring aop 核心概念
    • Target : 被拦截下来的对象(要被增强的对象)
    • Join Point : 连接点,,, 可以被切面插入的地方
    • Pointcut : 切点,, 被切面增强的连接点
    • Advice: 通知,切点在连接处执行的代码,增强
    • Aspect : 切面 , 通知和切点
    • Weaving : 织入,,将切面应用到 Target的过程,,可以在编译的时候weaving,也可以在类加载的时候,,也可以在运行的时候,,织入
    • introduction: 引介,,,,为某个类,增加新的方法或者属性,,,
      aop的使用

      定义一个增强:

      public class CalculatorAdvice implements MethodBeforeAdvice {
          /**
           *
           * @param method 当前的方法
           * @param args  方法参数
           * @param target  当前对象
           * @throws Throwable
           */
          @Override
          public void before(Method method, Object[] args, Object target) throws Throwable {
              System.out.println(method.getName()+" 开始执行。。。");
          }
      }
      

      xml中配置aop:

          
          
      
              
              
          
      

      这个CalculatorImpl 的类被增强了,,产生了一个新的代理类,,这个容器里面的CalculatorImpl的bean,,被这个新的代理的bean替换掉了,,

        public static void main(String[] args) {
              ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
              // 这里返回的是一个代理对象,,,并不是注入spring中的
              ICalculator bean = ctx.getBean(ICalculator.class);
      //        CalculatorImpl calculator = (CalculatorImpl) ctx.getBean("calculator");
      //        System.out.println("calculator = " + calculator);
              bean.add(1,2);
              bean.minus(1,2);
          }
      

      另一种配置xml:

      public class LogAdvice {
          public void before(JoinPoint jp){
              // 方法名
              String name = jp.getSignature().getName();
              System.out.println(name+"开始执行。。");
          }
          public void after(JoinPoint jp){
              String name = jp.getSignature().getName();
              System.out.println(name+"执行结束。。");
          }
          public void exception(JoinPoint jp,Exception e){
              String name = jp.getSignature().getName();
              System.out.println(name+"异常。。"+e.getMessage());
          }
          /**
           * 目标方法的返回值,,必须和这里的参数相匹配,,,该方法才会被触发
           * @param jp
           * @param result
           */
          public void returnAdvice(JoinPoint jp,int result){
              String name = jp.getSignature().getName();
              System.out.println(name+"返回值。。"+result);
          }
          public Object around(ProceedingJoinPoint pjp) throws Throwable {
              long startTime = System.currentTimeMillis();
              Object proceed = pjp.proceed(new Object[]{100,99});
              long endTime = System.currentTimeMillis();
              System.out.println(pjp.getSignature().getName()+"执行耗时"+(endTime-startTime));
              return proceed;
          }
      }
      
          
          
          
              
              
                  
                  
      
                  
                  
                  
              
          
      

      java代码配置aop:使用自动扫描带@Aspect的切面

      /**
       *
       *
       * aspect =  pointcut + advice
       **/
      @Aspect
      public class LogAspect {
          @Pointcut("execution(* com.cj.CalculatorImpl.*(..))")
          public void pc1(){}
          @Before("pc1()")
          public void before(JoinPoint jp){
              // 方法名
              String name = jp.getSignature().getName();
              System.out.println(name+"开始执行。。");
          }
          @After("pc1()")
          public void after(JoinPoint jp){
              String name = jp.getSignature().getName();
              System.out.println(name+"执行结束。。");
          }
          @AfterThrowing(value = "pc1()",throwing = "e")
          public void exception(JoinPoint jp,Exception e){
              String name = jp.getSignature().getName();
              System.out.println(name+"异常。。"+e.getMessage());
          }
          /**
           * 目标方法的返回值,,必须和这里的参数相匹配,,,该方法才会被触发
           * @param jp
           * @param result
           */
          @AfterReturning(value = "pc1()",returning = "result")
          public void returnAdvice(JoinPoint jp,int result){
              String name = jp.getSignature().getName();
              System.out.println(name+"返回值。。"+result);
          }
          @Around("pc1()")
          public Object around(ProceedingJoinPoint pjp) throws Throwable {
              long startTime = System.currentTimeMillis();
              Object proceed = pjp.proceed(new Object[]{100,99});
              long endTime = System.currentTimeMillis();
              System.out.println(pjp.getSignature().getName()+"执行耗时"+(endTime-startTime));
              return proceed;
          }
      }
      
          
          
      
          
      

      纯java类写法:

      需要在切面上添加注解@EnableAspectJAutoProxy,这个注解是用来识别切面的,相当于在xml中配置

      @Aspect
      @Component
      // 这个注解是用来识别切面的,,相当于
      @EnableAspectJAutoProxy
      public class LogAspect {
      ...
      }
      
      @Configuration
      @ComponentScan
      public class JavaConfig {
      }
      
      spring aop 动态代理

      如果有接口,用的jdk动态代理,,

      没有接口,用的cglib动态代理

      如果有接口,但是你不想使用jdk动态代理,而是使用cglib,,在@EnableAspectJAutoProxy 设置proxyTargetClass=true 就会使用cglib代理

      spring aop拦截
      • execution : 零侵入的拦截规则
      • 注解

        @annotation():方法上面有这个注解

        @within() : 类上面有这个注解

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]