zoukankan      html  css  js  c++  java
  • Spring注解驱动开发6:Spring扩展原理

    Spring注解驱动开发系列:

    1. Spring注解驱动开发1:组件注册
    2. Spring注解驱动开发2:生命周期和属性赋值
    3. Spring注解驱动开发3:自动装配
    4. Spring注解驱动开发4:AOP使用和原理
    5. Spring注解驱动开发5:Spring声明式事务
    6. Spring注解驱动开发6:Spring扩展原理

    Spring注解驱动开发6:Spring扩展原理

    BeanFactoryPostProcessor

    例子

    编写MyBeanFactoryPostProcessor类如下:

    @Repository
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanFactoryPostProcessor....invoke");
            int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            System.out.println("总共有:" + beanDefinitionCount);
            System.out.println("分别是:");
            for (String beanDefinitionName : beanDefinitionNames) {
                System.out.println(beanDefinitionName);
            }
        }
    }
    

    编写配置类代码如下:

    //配置类==配置文件
    @Configuration
    //开启自动包扫描,传入要扫描的包路径
    @ComponentScan(basePackages = "com.lin.springL")
    public class MainConfigure {
    
    }
    

    编写测试类代码如下:

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new
                    AnnotationConfigApplicationContext(MainConfigure.class);
        }
    }
    

    运行得到结果:

    MyBeanFactoryPostProcessor....invoke
    总共有:8
    分别是:
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfigure
    myBeanFactoryPostProcessor
    

    在容器初始化的时候就会执行,具体执行过程可以查看我的Spring源码篇。

    唯一要关注的是,执行BeanFactoryPostProcessor的时候,这时候BeanFactory只有Bean的定义BeanDefinition,还没有初始化Bean。

    具体调用链,可以通过Debug直接查看:

    image-20200519234906988

    最终的具体细节就是对所有的BeanFactoryPostProcessor遍历执行:

    private static void invokeBeanFactoryPostProcessors(
          Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    
       for (BeanFactoryPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessBeanFactory(beanFactory);
       }
    }
    

    BeanDefinitionRegistryPostProcessor

    Bean定义信息注册器的后置处理器,实现了BeanFactoryPostProcessor接口,与其不同的是:

    • BeanFactoryPostProcessor是在Bean的定义信息加载完后执行,而BeanDefinitionRegistryPostProcessor是在bean定义信息正要加载的时候执行。

    例子

    编写MyBeanDefinitionRegistryPostProcessor类:

    @Repository
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor----postProcessBeanDefinitionRegistry");
            //可以在这里创建自己的BeanDefinition
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Lin.class);
            registry.registerBeanDefinition("lin", rootBeanDefinition);
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("MyBeanDefinitionRegistryPostProcessor----postProcessBeanFactory");
        }
    }
    

    更改MainTest如下:

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new
                    AnnotationConfigApplicationContext(MainConfigure.class);
            Lin bean = applicationContext.getBean(Lin.class);
            System.out.println(bean);
        }
    }
    

    运行得到结果:

    MyBeanDefinitionRegistryPostProcessor----postProcessBeanDefinitionRegistry
    MyBeanDefinitionRegistryPostProcessor----postProcessBeanFactory
    MyBeanFactoryPostProcessor....invoke
    com.lin.springL.pojo.Lin@166fa74d
    

    可以看到MyBeanDefinitionRegistryPostProcessor先于MyBeanFactoryPostProcessor执行。

    BeanFactory就是根据BeanDefinitionRegistry所定义的BeanDefinition来创建对应的Bean实例。因此在此可以通过registry.registerBeanDefinition("lin", rootBeanDefinition);来注册自定义的Bean定义,之后就会被BeanFactory初始化。

    private static void invokeBeanDefinitionRegistryPostProcessors(
          Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
       for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessBeanDefinitionRegistry(registry);
       }
    }
    

    ApplicationListener

    监听容器中发布的事件,完成事件驱动模型的开发。

    例子

    编写MyApplicationListener类如下:

    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
        //当容器中发布此事件后,方法触发
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            System.out.println("收到事件:" + event);
        }
    }
    

    编写MainTest类代码如下:

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new
                    AnnotationConfigApplicationContext(MainConfigure.class);
            applicationContext.close();
        }
    }
    

    运行得到如下输出:

    收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:02:43 CST 2020]; root of context hierarchy]
    收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:02:43 CST 2020]; root of context hierarchy]
    

    可以看到容器的启动和关闭事件都被监听到了,因此可以监听ApplicationEvent及其子类的事件,所以如果需要自定义事件,继承ApplicationEvent后由Spring发布消息,然后就可以在ApplicationListener进行监听操作了。

    自定义发布事件

    更改MainTest代码如下:

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new
                    AnnotationConfigApplicationContext(MainConfigure.class);
            applicationContext.publishEvent(new ApplicationEvent(new String("自定义事件")) {
            });
            applicationContext.close();
        }
    }
    

    执行得到输出:

    收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:10:32 CST 2020]; root of context hierarchy]
    收到事件:com.lin.springL.MainTest$1[source=自定义事件]
    收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:10:32 CST 2020]; root of context hierarchy]
    

    我们发布的消息也成功被监听到。

    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
       ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
       for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          Executor executor = getTaskExecutor();
          if (executor != null) {
             executor.execute(new Runnable() {
                @Override
                public void run() {
                   invokeListener(listener, event);
                }
             });
          }
          else {
             invokeListener(listener, event);
          }
       }
    }
    

    @EventListener

    上面实现监听需要自己定义类实现ApplicationListener,在这里可以使用注解的方式,让任意一个方法成为监听方法。

    例子

    编写UserService类如下:

    @Service
    public class UserService {
        //监听ApplicationEvent事件
        @EventListener(classes = {ApplicationEvent.class})
        public void listener(ApplicationEvent event) {
            System.out.println("UserService监听事件:" + event);
        }
    }
    

    编写配置类如下:

    //配置类==配置文件
    @Configuration
    //开启自动包扫描,传入要扫描的包路径
    @ComponentScan(basePackages = "com.lin.springL")
    public class MainConfigure {
    
    }
    

    编写MainTest类如下:

    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new
                    AnnotationConfigApplicationContext(MainConfigure.class);
            applicationContext.publishEvent(new ApplicationEvent(new String("自定义事件")) {
            });
            applicationContext.close();
        }
    }
    

    运行得到输出:

    UserService监听事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:51:57 CST 2020]; root of context hierarchy]
    UserService监听事件:com.lin.springL.MainTest$1[source=自定义事件]
    UserService监听事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:51:57 CST 2020]; root of context hierarchy]
    

    可以看到也是可以监听到事件。

  • 相关阅读:
    pycharm中快捷键的使用
    Python中用format函数格式化字符串的用法
    Python eval()函数的用法
    python中的字符数字之间的转换函数
    python_控制台输出带颜色的文字方法
    Alpha通道是什么意思,和rgb通道有什么区别
    转载-【深度学习】深入理解Batch Normalization批标准化
    深度卷积网络-Inception系列
    微调Inception V3网络-对Satellite分类
    h5模型文件转换成pb模型文件
  • 原文地址:https://www.cnblogs.com/jinchengll/p/12922380.html
Copyright © 2011-2022 走看看