• spring注解-扩展原理


      AnnotationConfigApplicationContext(IOC容器)的有参构造方法中,在refresh()里对这些组件进行初始化

    BeanPostProcessor

      bean后置处理器,bean创建对象初始化前后进行拦截工作的

    BeanFactoryPostProcessor

      refresh()里的invokeBeanFactoryPostProcessors(beanFactory)来初始化BeanFactoryPostProcessor(beanFactory后置处理器,在所有的bean定义信息保存到beanFactory并进行标准初始化之后调用,来定制和修改BeanFactory的内容)

    • String[] postProcessorNames=beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false)
      • 从beanFactory中找到所有类型是BeanFactoryPostProcessor的组件,循环遍历postProcessorNames根据组件优先级加入到不同的集合里(实现了PriorityOrdered的直接在循环中就注册了beanFactoryPostProcessor,其余的之后再一次循环遍历进行注册)
      • 优先级高的集合先执行invokeBeanFactoryPostProcessors(postProcessors,beanFactory),该方法遍历调用postProcessors集合里的对象.postProcessBeanFactory(beanFactory)

    BeanDefinitionRegistryPostProcessor

      继承BeanFactoryPostProcessor接口,在invokeBeanFactoryPostProcessors(beanFactory)中,在所有的bean定义信息将要被加载、BeanFactoryPostProcessor初始化之前进行工作

    • String[] postProcessorNames=beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      • 从beanFactory中找到所有类型是BeanDefinitionRegistryPostProcessor的组件,也是根据优先级执行invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry),之后依次触发所有的postProcessBeanDefinitionRegistry(registry)可以给容器中再额外添加一些组件

    结论

    • invokeBeanFactoryPostProcessors()先从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件(BeanDefinitionRegistryPostProcessor执行过的bean都会保存到一个集合里,执行到BeanFactoryPostProcessor的时候就会进行判断,如果存在说明已经执行过了)
    • 依次触发所有的postProcessBeanDefinitionRegistry()
    • 再来触发BeanFactoryPostProcessor.postProcessBeanFactory()
    • 最后再来从容器中找到BeanFactoryPostProcessor组件,然后依次触发postProcessBeanFactory()
    @Component
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            // TODO Auto-generated method stub
            System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount());
        }
    
        //BeanDefinitionRegistry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例;
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            // TODO Auto-generated method stub
            System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
            //RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
            registry.registerBeanDefinition("hello", beanDefinition);
        }
    
    }

    ApplicationListener

      监听容器中发布的事件;在refresh()里的registerListeners()里执行getBeanNamesForType(ApplicationListener.class, true, false)获取所有的监听事件,并将它们保存到ApplicationEventMulticaster的listener集合中

     public interface ApplicationListener<E extends ApplicationEvent>  //监听 ApplicationEvent 及其下面的子事件

    步骤

    • 实现ApplicationListener接口来监听某个事件(ApplicationEvent及其子类)并加入到容器。只要容器中有相关事件的发布,我们就能监听到这个事件
      • ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件
      • ContextClosedEvent:关闭容器会发布这个事件
    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    
        //当容器中发布此事件以后,方法触发
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            // TODO Auto-generated method stub
            System.out.println("收到事件:"+event);
        }
    
    }
    • 发布事件
    applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
            });

     原理

    • ContextRefreshedEvent
      • 在refresh()里的finishRefresh()中执行了publishEvent(new ContextRefreshedEvent(this));在容器刷新完成的最后一步方法里发布ContextRefreshedEvent事件
    • ContextClosedEvent
      • 执行applicationContext.close()关闭容器的doClose()中执行了publishEvent(new ContextClosedEvent(this))

      所有的事件发布都调用了publishEvent(),而在这方法里主要做了这几件事:

    • 获取事件的多播器(派发器):getApplicationEventMulticaster(),并通过multicastEvent()派发事件,在该方法中获取到所有的ApplicationListener进行遍历(如果有Executor,可以支持使用Executor进行异步派发;否则,同步的方式直接执行invokeListener(listener, event)),拿到listener回调onApplicationEvent()

     @EventListener

      使用EventListenerMethodProcessor处理器解析方法上的@EventListener,它实现SmartInitializingSingleton的afterSingletonsInstantiated();

      在refresh()里的finishBeanFactoryInitialization(beanFactory)里创建完所有单例bean后,会获取所有的bean判断是否是SmartInitializingSingleton类型的,如果是就调用afterSingletonsInstantiated()

    @EventListener(classes={ApplicationEvent.class})
        public void listen(ApplicationEvent event){
            System.out.println("监听到的事件:"+event);
        }

    事件的多播器

      在refresh()里的initApplicationEventMulticaster()中初始化ApplicationEventMulticaster,先去容器中找有没有id=“applicationEventMulticaster”的组件,如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);并通过beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster)注册到容器中去,在其他组件要派发事件就可以自动注入这个applicationEventMulticaster

  • 相关阅读:
    20201304杨淑钰+快速浏览教材
    20201304 自我介绍
    熟悉编程语言
    俄罗斯方块游戏代码的改写
    2020 -2021-1 20201319 《信息安全专业导论》第八周学习总结
    如何学好编程
    2020-2021-1 20201319 《信息安全专业导论》第七周学习总结
    2020-2021-1 20201319 《信息安全专业导论》第六周学习总结
    实现进制转换伪代码
    斐波那契数列递归实现
  • 原文地址:https://www.cnblogs.com/edda/p/13493780.html
Copyright © 2020-2023  润新知