spring03-aop

2024-06-30 1213阅读
  • 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购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]