zoukankan      html  css  js  c++  java
  • Spring注解(AOP)

    底层动态代理

      程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式

    导入aop的相关模块

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>

    动态感知业务类运行的状态

        通知: 前置 @Before  后置 @After  环绕 @Around 异常@AfterThrowing  返回 @AfterReturning

        补充环绕通知: 动态代理,手动推进目标方法运行(joinPoint.proceed() )

    步骤:

    编写切面类

    在切面类里面  把每个方法 何时何地切入都指定好

    将切面类和业务逻辑类 都添加到容器中

    告诉容器 哪个是切面类@Aspect

    在 xml中  <aop: aspectj-autoproxy> </aop:aspectj-autoproxy>    开启基于注解版的切面功能

    注解中: 在当前的配置类加入  @EnableAspectJAutoProxy 启用基于注解的aop模式

    正常代码:

    @Component
    public class Mathcalculator {
         public int div(int i , int j) {
             System.out.println("Mathcalculator--div被调用");
             return i/j;
         }
    }

    切面类:

    @EnableAspectJAutoProxy
    @Configuration
    public class AOPConfig {
       @Bean  //业务逻辑类注册到容器
        public Mathcalculator mathcalculator() {
            return new Mathcalculator();
        }
       
       @Bean  // 切面类注册到容器中
       public LogAspects logAspects() {
           return new LogAspects();
       }
    }

    测试:

    public class test {
        @Test 
        public void test01(){  
            //使用无参构造器  创建applicationContext  (详情自己研究下有参构造器的方法)
            AnnotationConfigApplicationContext applicationContext=
                    new AnnotationConfigApplicationContext(AOPConfig.class);
            Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
            bean.div(1, 1);
           //设置需要激活的环境
            applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
           //注册主配置类
            applicationContext.register(Profile.class);    
           //启动刷新容器
           applicationContext.refresh();
          }  
    } 

    结果:

     

    升级:

    切面类

    @Aspect
    public class LogAspects {
      //抽取公共的切入点表达式  本类的  如果是别的类的 写全名就OK了
        
        @Pointcut("execution(public int com.toov5.config.Mathcalculator .*(..))" )
        public void pointCut() {
            
        }
    // @Before("public int com.toov5.config.Mathcalculator.div(int , int)")
       @Before( "pointCut()" )
        public void logStart(JoinPoint joinpoint) {  //获取签名 获取方法
          Object[] args = joinpoint.getArgs(); //目标方法 运行时候需要的参数表
            System.out.println("除法运行@Before"+joinpoint.getSignature().getName()+"运行时参数表"+args );
        }
        @After( "pointCut()" ) //运行异常与否 都要执行的
        public void logEnd(JoinPoint joinPoint) {
            System.out.println(joinPoint.getSignature().getName()+"除法结束@After");
        }
        @AfterReturning(value="pointCut()", returning="result")
        public void logReturn(JoinPoint joinpoint,Object result ) { //result 接受返回值
            System.out.println(joinpoint.getSignature().getName()+"除法正常运行@AfterReturning,结果:"+result);
        } 
        @AfterThrowing(value = "pointCut()", throwing="e")
        public void logException(JoinPoint joinpoint, Exception e) {
            System.out.println( joinpoint.getSignature().getName()+"除法异常@AfterThrowing"+e.getMessage());
        }
    }

    配置:

    @EnableAspectJAutoProxy
    @Configuration
    public class AOPConfig {
       @Bean  //业务逻辑类注册到容器
        public Mathcalculator mathcalculator() {
            return new Mathcalculator();
        }
       
       @Bean  // 切面类注册到容器中
       public LogAspects logAspects() {
           return new LogAspects();
       }
    }

    测试类:

    public class test {
        @Test 
        public void test01(){  
            //使用无参构造器  创建applicationContext  (详情自己研究下有参构造器的方法)
            AnnotationConfigApplicationContext applicationContext=
                    new AnnotationConfigApplicationContext(AOPConfig.class);
            Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
            bean.div(1, 1);
           //设置需要激活的环境
            applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
           //注册主配置类
            applicationContext.register(Profile.class);    
           //启动刷新容器
           applicationContext.refresh();
          }  
    } 

    结果:

    JointPoint 要写一定要写在 参数的首位! 

     三步走:

       1  将业务逻辑组件和切面类都加入到容器,告诉Spring哪个是切面类(@Aspect)

       2 在切面类上的每一个通知方法上标注 通知注解,告诉Spring合适何地运行(切入点表达式)

       3 开启基于注解的aop模式 与config上 

    总结:

    aop的原理


     加入@EnableAspectJAutoProxy  才有AOP

     

    继续点开看

    利用AspectJAutoProxyRegistrar  给自定义容器中注册bean

      给容器注册一个AnnotationAwareAspectJAutoProxyCreator   自动代理创建器

       可以一直追踪其父类:

          

     实现了 SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware  

                                       后置处理器                                        

    关注后置处理器的工作  Bean初始化完成前后做的事情

     BeanFactory                自动注入 

     AbstractAutoProxyCreator :

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
    }

     然后是与后置处理器有关的: 

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

     有后置处理器的逻辑

     AbstractAutoProxyCreator   类

    AnnotationAwareAspectJAutoProxyCreator 类  initBeanFactory

    启动后

    1、  传入主配置类  创建 IOC容器

    2、  注册配置类 调用refresh() 刷新容器

    3、 registerBeanPostProcessors(beanFactory)  注册bean的后置处理器 方便拦截bean的创建

           1先获取ioc容器中已经定义了需要创建对象的所有BeanPostProcessor

           2给容器加别的BeanPostProcessor

           3优先注册实现了PriorityOrdered接口的BeanPostProcessor

           4在给容器中注册实现了Ordered接口的BeanPostProcessor

           5注册没实现优先级接口的BeanPostProcessor

                 创建internalAutoProxyCreator的BeanPostProcessor

                       创建Bean的实例

                       populateBean 初始化Bean

                               1、 invokeAwareMethods() 处理Aware接口的方法回调

                               2、 applyBeanPostProcessorsBeforeInitialization() 应有后置处理器的BeforeInitialization( ) 

                               3、invokeInitMethods() 自定义的初始化方法

                               4、applyBeanPostProcessorsAfterInitialization ()  执行后置处理器的 postProcessAfterInitialization

    4、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功; aspectJAdvisorBuilder

       6 把beanPostProcessor注册到BeanFactory中 调用addBeanPostProcessor(postProcessor)

  • 相关阅读:
    风讯DotNetCMS sp5安装笔记
    datalist中实现自动编号写法
    windows server 2008 自动登录设置
    C#软件监控外部程序运行状态
    WPF启动屏幕SplashScreen
    Windows Server 2019 在桌面上显示“我的电脑”
    使用jquery的load方法加载html页面,html引入的js无效
    sql查询文章上一篇下一篇
    C#调用user32.dll Win32的API函数
    C#调用dll提示"试图加载格式不正确的程序
  • 原文地址:https://www.cnblogs.com/toov5/p/10667255.html
Copyright © 2011-2022 走看看