• 扩展


    BeanFactoryPostProcessor

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

    BeanFactoryPostProcessor: beanFactory的后置处理器,在Beanfactory标准初始化之后调用;所有的Bean定义已经保存加载到beanFactory/.但是Ban实例还未创建

    实现接口的Bean:

    @Component
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("postProcessBeanFactory");
            int count = beanFactory.getBeanDefinitionCount();
            String[] names = beanFactory.getBeanDefinitionNames();
            System.out.println("当前BeanFactory中有"+count+"个Bean");
            System.out.println(Arrays.asList(names));
            
        }
    
    }

     config:

    @Configuration
    @ComponentScan("com.toov5.ExtBean")
    public class ExtConfig {
        @Bean
        public Boss boss() {
            return new Boss();
        }
    }

    Test:

    public class test {
        @Test 
        public void test01(){    
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
            applicationContext.close();
          }  
    } 

    结果: 看到执行过程如下

    步骤:

       1  ioc容器创建对象

       2 invokeBeanFactoryPostProcessors(beanFactory) ; 执行BeanfactoryPostProcessor; 如何找到所有的BeanFactoryPostProcessor并执行他们的方法

            a,直接在BeanFactory中找到所有类型是BeanfactoryPostProcessor的组件,并执行他们的方法。

            b,在初始化创建其他组件前面执行  

    MyBeanDefinitionRegistryPostProcessor :
    @Component
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("BeanDefinitionRegistryPostProcessor..bean的数量"+beanFactory.getBeanDefinitionCount());
            
        }
       //BeanDefinitionRegistry  Bean定义信息的保存中心  以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个Bean定义信息创建bean实例
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("BeanDefinitionRegistryPostProcessor..Bean的数量"+registry.getBeanDefinitionCount());
            //可以自己注册Bean
            //    RootBeanDefinition beanDefinition = new RootBeanDefinition(Car.class);
           //或者这样,与上面效果是一样的
            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class).getBeanDefinition();
            registry.registerBeanDefinition("helloBeanName", beanDefinition);
        }
    
    }

     执行test方法后:

      

     可以看出 优先于 

    BeanFactoryPostProcessor  执行

    利用 

    BeanDefinitionRegistryPostProcessor  给容器中再额外添加一些组件

    原理: 

        1 ioc创建对象

        2 refresh() ---> invokeBeanFactoryPostProcessors(beanFactory)

       3 从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件

         1 一次触发所有的postProcessBeanDefinitionRegistry() 方法

         2 再来触发postProcessBeanFactory() 方法 

    ApplicationListener: 监听容器中发布的时间。时间 驱动模型开发

        public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

          监听ApplicationEvent 及其下面的子事件

    容器刷新事件 容器关闭事件

     步骤:

       1 写一个监听器来监听某个事件(ApplicationEvent及其子类)

       2 把监听器注册到容器中

       3 只要容器中有相关事件的发布,就能监听到这个事件

         ContextRefreshedEvent: 容器刷新完成(所有bean都完全创建) 会发布事件

         ContextClosedEvent: 关闭容器会发布这个事件

     4 发布一个事件

        

    监听:

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

    test:  发布了一个事件

    public class test {
        @Test 
        public void test01(){    
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
            //发布事件
            applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
            });
            applicationContext.close();
          }  
    } 

    结果:

    原理:

      ContextRefreshedEvent事件

           1、容器创建对象 refresh()  

           2、 finishRefresh() 容器刷新完成,容器刷新完成会发布ContextRefreshedEvent事件。我们也可以自己发布事件,容器关闭会发布事件

           3、publishEvent(new ContextRefreshedEvent(this) )

                事件发布流程:

                         获取事件的多播器(派发器): getApplicationEventMulticaster()

                         multicastEvent派发事件

                         获取到所有的ApplicationListener: 如果有Executor 可以支持使用Executor进行异步派发,否则,同步的方法直接知心Listener方法 invokeListener(listener, event)

                         拿到listener回调onApplicationEvent方法

                                

    @EventListener   跟实现Listener接口实现的效果是一样的

       service

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

     config

      

    @Configuration
    @ComponentScan("com.toov5.service")
    public class ExtConfig {
        @Bean
        public Boss boss() {
            return new Boss();
        }
    }

    test:

    public class test {
        @Test 
        public void test01(){    
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
            //发布事件
            applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
            });
            applicationContext.close();
          }  
    } 

    结果:

     监听器的实现ApplicationListener监听某个事件, ApplicationEvent及其子类

     @EventListener

    原理: 使用EventListenerMethodProcessor处理器来解析方法上的@EcentListener

    SmatInitializationSingleton原理 

       ioc容器创建对象并refresh()

       finishBeanFactoryInitialization(beanFactory) 初始化剩下的单实例bean

               先创建所有的单实例bean getBean()

              获取所有创建好的单实例bean,判断是否是SmartInitatializingSingleton类型的。是就调用afterSingletonInstantiated() 

  • 相关阅读:
    js幻灯片效果!
    构造函数和析构函数的简单说明
    ASP.NET接口的基础使用例子
    带预览图的js切换效果!
    在win7系统中安装sqlserver2005出现 [Microsoft][SQL Native Client]客户端不支持加密问题!
    Win7开启无线共享上网的方法
    C# 结构体 简明介绍
    C#访问修饰符简单说明
    C#不定长参数的使用
    研究了一下Google Ajax Search API, 给博客做了个样品
  • 原文地址:https://www.cnblogs.com/toov5/p/10687177.html
Copyright © 2020-2023  润新知