zoukankan      html  css  js  c++  java
  • Spring ApplicationContext 初始化流程

    主题

    学习记录一下applicationContext在初始化过程中做的一些操作..

    从全局整体来看.不会涉及太多细节.

    applicationcontext的refresh方法是一个startup method.算是spring启动的一个方法.它处理各种配置,不管是XML还是properties还是啥.创建了各种bean.算是一个最核心的方法.

    refresh方法里面包含了一大堆模板方法.每个模板都做了一些事情,相当于一个小步骤..

    从代码整体来看大概包含了这么一些步骤.其中2,3,4,5,6这几部是我个人觉得最核心的步骤.我想特别记录下我的想法

    1. prepareRefresh

     1     /**
     2      * Prepare this context for refreshing, setting its startup date and
     3      * active flag as well as performing any initialization of property sources.
     4      */
     5     protected void prepareRefresh() {
     6         this.startupDate = System.currentTimeMillis();
     7         this.active.set(true);
     8 
     9         if (logger.isInfoEnabled()) {
    10             logger.info("Refreshing " + this);
    11         }
    12 
    13         // Initialize any placeholder property sources in the context environment
    14         initPropertySources();
    15 
    16         // Validate that all properties marked as required are resolvable
    17         // see ConfigurablePropertyResolver#setRequiredProperties
    18         getEnvironment().validateRequiredProperties();
    19 
    20         // Allow for the collection of early ApplicationEvents,
    21         // to be published once the multicaster is available...
    22         this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    23     }
    View Code

    这个方法基本啥都没做.留给子类ac去做自定义的操作.

    比如web环境下的ac可能会将servletConfig或者servletContext里配置的一些参数值也当做属性值加入到spring中.因为你的spring的部分配置可能会依赖这些web.xml里的配置

    另外就是对必要属性的验证.如果有必要的话可以自己去写一个ac继承spring,然后重写initPropertySources方法去设置你觉得必要的属性.然后当getEnvironment().validateRequiredProperties();

    的时候如果没有找到你之前setRequiredProperties的那些属性.就会提示报错.

    2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    获取BF这个步骤主要作用就是构造一个bf.然后去加载对应的beanDifination信息.

        /**
         * Tell the subclass to refresh the internal bean factory.
         * @return the fresh BeanFactory instance
         * @see #refreshBeanFactory()
         * @see #getBeanFactory()
         */
        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (logger.isDebugEnabled()) {
                logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
            }
            return beanFactory;
        }

    getBeanFactory方法就是获取当前这个ac里设置的bf,没啥好说的.主要看看refreshBeanFactory这个方法里面做了啥.

     1     /**
     2      * This implementation performs an actual refresh of this context's underlying
     3      * bean factory, shutting down the previous bean factory (if any) and
     4      * initializing a fresh bean factory for the next phase of the context's lifecycle.
     5      */
     6     @Override
     7     protected final void refreshBeanFactory() throws BeansException {
     8         if (hasBeanFactory()) {
     9             destroyBeans();
    10             closeBeanFactory();
    11         }
    12         try {
    13             DefaultListableBeanFactory beanFactory = createBeanFactory();
    14             beanFactory.setSerializationId(getId());
    15             customizeBeanFactory(beanFactory);
    16             // 这里不同的ac可能会有不同的loadDefination的方法,比如AnnotationConfigWebApplicationContext就会扫描注解注册BD
    17             loadBeanDefinitions(beanFactory);
    18             synchronized (this.beanFactoryMonitor) {
    19                 this.beanFactory = beanFactory;
    20             }
    21         }
    22         catch (IOException ex) {
    23             throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    24         }
    25     }
    View Code

    2.1 shuwdown之前的bf

    如果当前这个ac已经有bf了(比如之前ac的refresh就调用过)了.那这里需要把这个bf shutdown.

    比如把bf里的各种缓存的map情况.然后所有的单例bean如果impl了DisposableBean,还需要调用它的destroy方法去做相应的操作.

     

    2.2 创建bf

    DefaultListableBeanFactory beanFactory = createBeanFactory();

    createBeanFactory默认返回的是DefaultListableBeanFactory类的实例.目前为止spring中还没看到其他继承这个BF的实现类.基本都是用这个类作为默认的BF.可能因为功能已经足够强大了吧..另外因为ApplicationContext也继承了BF,所以很多操作会在ac里操作掉..根据ac的不同实现做不同的操作.可能这也是bf没有这么多实现的原因吧...

    2.3 配置bf

    customizeBeanFactory(beanFactory);

    这是一个模板方法.允许子类ac去实现他.对bf进行一些个性化配置.比如是否需要解决单例的循环依赖呀? 是否允许beanDifination多次定义被覆盖呀? 

    bf里配置还蛮多的..不过我看源码里目前子类ac也没啥进行定制的...

    2.4 加载bd

    loadBeanDefinitions(beanFactory);

    BeanFactory的作用就是读取bean的配置信息变成内存中的BeanDifination.然后在创建bean的时候根据这个bd去构造具体的bean.

    不同的bean的配置方式可能各种各样.比如有XML的.Properties的.传统注解@Service@Autowired的.又或是@Configuration这种java config方式的..但是他们在内存中都是通过BeanDifination来表示的(可能是不同子类).

    不同的ApplicationContext代表了不同的环境.比如适用于web环境的WebApplicationContext,也有传统单独使用spring的时候的XML里的ClassPathXmlApplicationContext等等

    这些不同的ac加载bd的方式也会各有不同.所以在这个loadBeanDefinitions模板方法里就是要根据不同的ac去实现不同的加载bd的方式.

    比如XML的ac就应该委托XmlBeanDefinitionReader去读取bean形式的配置.转化成BeanDifination注册到BF中.

    而支持Annotation的ac就应该委托AnnotatedBeanDefinitionReader这种reader去扫描Java源码.注册相应的BD.

    当然.注册的BD不一定就是我们代码里用到的那些bean对应的bd.也可能是一些BeanPostProcessor或者子接口的实现类.

    因为比如InstantiationAwareBeanPostProcessor类似这种特殊的接口都是参与Spring的生命周期可以在一些必要的时候替换掉原始的bean.或者对bean的属性进行一些加工.

    比如@Autowired这种操作就是用到特殊的bpp..AutowiredAnnotationBeanPostProcessor..同理@Configuration也是一样..

    所以说不同的bean的配置方式在spring创建对应的bean过程中走的流程可能是不一样的,这也是Spring比较灵活的地方.

    有些bean会被适用于它的bpp去处理去生成或者去注入属性.而有一些可能就是比较原生,直接通过bd被BeanWrapper给new出来.

    3.prepareBeanFactory

     1     /**
     2      * Configure the factory's standard context characteristics,
     3      * such as the context's ClassLoader and post-processors.
     4      * @param beanFactory the BeanFactory to configure
     5      */
     6     protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     7         // Tell the internal bean factory to use the context's class loader etc.
     8         beanFactory.setBeanClassLoader(getClassLoader());
     9         beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    10         beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    11 
    12         // Configure the bean factory with context callbacks.
    13         beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    14         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    15         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    16         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    17         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    18         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    19 
    20         // BeanFactory interface not registered as resolvable type in a plain factory.
    21         // MessageSource registered (and found for autowiring) as a bean.
    22         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    23         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    24         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    25         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    26 
    27         // Detect a LoadTimeWeaver and prepare for weaving, if found.
    28         if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    29             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    30             // Set a temporary ClassLoader for type matching.
    31             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    32         }
    33 
    34         // Register default environment beans.
    35         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    36             beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    37         }
    38         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    39             beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    40         }
    41         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    42             beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    43         }
    44     }

    大致做的事情就是

    3.1 SPEL

    设置spelResolver用于spel的解析. spel单独就有一个自己的模块. 具体就不说了.

     

    3.2 PropertyEditorRegistrar

    设置PropertyEditorRegistrar. spring的配置文件很多都是XML或者property这种文本.读取出来的都是字符串.但是java对象有各种类型的属性.所以生成bean的时候需要做一些类型转化

    比如 String -> Int类似这种, 就需要自己去写一个PropertyEditorSupport的实现类,去impl setAsText(String) 的方法.把XML里得到的字符串转化成Java对象里的Int值.Spring自带了很多这种Editor

    ResourceEditorRegistrar.java

    另外spring的类型转化也有很多种方法.这种PropertyEditorSupport(java.beans包下的)可能是早期的方案.后续的SPring版本中有一些地方转化用到了conversionService. 里面又设计到其他的一些类型转化接口.

    可以参考我的这篇文章
    https://www.cnblogs.com/abcwt112/p/7447435.html

    3.3 注册BeanPostProcessor

    beanPostProcessor可以在bean初始化方法(比如XML里的init-method或者InitializingBean的afterPropertySet方法)前和后对bean进行加工或者返回一个wrapper替换掉原本的bean.

    注意的是bean的属性填充是在bpp2个操作之前的.就是populate(BeanFactory创建bean的一个利用BeanWrapper去设置bean的属性的时候回调用的方法)方法已经被调用过的.

    Spring在这里new了一个ApplicationContextAwareProcessor

     1     @Override
     2     public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
     3         AccessControlContext acc = null;
     4 
     5         if (System.getSecurityManager() != null &&
     6                 (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
     7                         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
     8                         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
     9             acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    10         }
    11 
    12         if (acc != null) {
    13             AccessController.doPrivileged(new PrivilegedAction<Object>() {
    14                 @Override
    15                 public Object run() {
    16                     invokeAwareInterfaces(bean);
    17                     return null;
    18                 }
    19             }, acc);
    20         }
    21         else {
    22             invokeAwareInterfaces(bean);
    23         }
    24 
    25         return bean;
    26     }
    27 
    28     private void invokeAwareInterfaces(Object bean) {
    29         if (bean instanceof Aware) {
    30             if (bean instanceof EnvironmentAware) {
    31                 ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    32             }
    33             if (bean instanceof EmbeddedValueResolverAware) {
    34                 ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
    35                         new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
    36             }
    37             if (bean instanceof ResourceLoaderAware) {
    38                 ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    39             }
    40             if (bean instanceof ApplicationEventPublisherAware) {
    41                 ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    42             }
    43             if (bean instanceof MessageSourceAware) {
    44                 ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    45             }
    46             if (bean instanceof ApplicationContextAware) {
    47                 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    48             }
    49         }
    50     }
    View Code

    对实现了一部分Aware的bean做方法调用.

    比如你的bean impl了ApplicationContextAware这个接口.那就会调用你的setApplicationContext方法去让你有机会将ac设置为你的bean里的一个属性.

    为什么Aware的一些接口要用这些内置的bpp去处理,而不是当做一般的bean注入?

    我个人觉得是第一,要控制是什么时候注入这些bean.比如如果只是在一般的populate属性的时候注入这个ac.那这个时候不是所有的bean都被new过..可能会有一些意想不到的问题.

    第二我觉得是因为ac和BeanFactory可能会有多个,比如早期没有springboot的时候.spring会有一个ac.然后springmvc自己也会有一个ac.有parent和child的关系.那你在一个bean里注入ac.就会有2个符合条件的ac选择.这也是有问题的.

    3.4 忽略部分类型bean的注入

    1         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    2         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    3         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    4         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    5         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    View Code

    为什么这些类型的bean不需要注入? 因为3.3里已经在bpp里处理了

    3.5 指定部分类型的bean注入

    1         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    2         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    3         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    4         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    View Code

    指定了一些bean的类型使用特定的bean注入..比如BeanFactory就使用当前这个ac对应的bf去注入即可.

    3.6 额外注册一些Bean

     1         // Detect a LoadTimeWeaver and prepare for weaving, if found.
     2         if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
     3             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
     4             // Set a temporary ClassLoader for type matching.
     5             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
     6         }
     7 
     8         // Register default environment beans.
     9         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    10             beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    11         }
    12         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    13             beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    14         }
    15         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    16             beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    17         }
    View Code

    如果有一些bean你没配置.那就会使用spring默认的配置.比如environment.你如果配置了.那就用你的bean

    4. postProcessBeanFactory(beanFactory);

    这个方法是一个模板方法,允许子类对bf做一些处理.

    比如一些web相关的ac会在这里add一些bpp比如ServletContextAwareProcessor来对servlet做一些处理

    或者在这里也可以get BF以后去调用方法增加一些BeanFactoryPostProcessor.

    5.invokeBeanFactoryPostProcessors(beanFactory);

    做到这个方法的时候BF已经加载完所有的BeanDifination了(详见第2节).但是任何bean都还没有被初始化(new).

    看方法名字就知道这个方法是去激活调用beanFactoryPostProcessors的相关方法的.

    beanFactoryPostProcessors这个接口还有一个子接口叫做BeanDefinitionRegistryPostProcessor.

    这个子接口的postProcessBeanDefinitionRegistry方法是处理BeanDefinitionRegistry用的.可能是个新增的接口.因为我看到网上很多博客上都只写了BFPP而没有写这个接口..(因为大部分文章介绍的是早期的spring)

    这个接口的会先于BFPP的postProcessBeanFactory掉用,他可以处理BeanDefinitionRegistry,有一些BF实现了这个接口,也有一些BF没有.绝大部分大部分ac使用的DefaultListableBeanFactory

    是实现了这个接口的.所以可以处理BeanDefinitionRegistryPostProcessor.

    BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry作用是给你一个机会去手动注册beanDifination..可以用这个接口去注册一些BeanFactoryPostProcessor..当然普通的BD也可以去注册或者修改.但是如果是这种目的的话最好可以使用BeanFactoryPostProcessor的postProcessBeanFactory.这样通用性更好.也更合理.

    BeanFactoryPostProcessor的postProcessBeanFactory用于修改BeanFactory或者去修改BF里的BeanDifination..

    一个典型的案例就是在早期版本的spring(还没用springboot的时候)我们会配置placeholderconfigurer.这个类就是实现了BeanFactoryPostProcessor接口.他会扫描所有bean里的属性.去把${}这种占位符替换成property文件里指定的值.常用于db的配置独立放在.properties文件中,datasource的配置放在bean.XML文件中. 

    所以invokeBeanFactoryPostProcessors(beanFactory);这个方法所做的事情就是.

    1.获取所有手动注册的BeanDefinitionRegistryPostProcessor.去调用postProcessBeanDefinitionRegistry.

    所谓的手动注册就是在之前几节的模板方法中直接调用ApplicationContext的addBeanFactoryPostProcessor方法注册的BeanDefinitionRegistryPostProcessor

    2.然后获取扫描bf中所有注册的BeanDefinitionRegistryPostProcessor.

    按PriorityOrdered > Ordered > rest 去排序,依次调用postProcessBeanDefinitionRegistry方法

    也就是说你的非手动注册的BeanDefinitionRegistryPostProcessor如果实现了PriorityOrdered接口.那肯定会比实现了Ordered接口的BeanDefinitionRegistryPostProcessor早调用.

    同样接口的.就按接口内定义的顺序排序.比如Ordered接口.就是数字越小排在越前面

    3.处理一般的BeanFactoryPostProcessor的postProcessBeanFactory方法.

    顺序和BeanDefinitionRegistryPostProcessor一样,也是 手动注册的> PriorityOrdered > Ordered > rest

      1 public static void invokeBeanFactoryPostProcessors(
      2             ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
      3 
      4         // Invoke BeanDefinitionRegistryPostProcessors first, if any.
      5         Set<String> processedBeans = new HashSet<String>();
      6 
      7         if (beanFactory instanceof BeanDefinitionRegistry) {
      8             BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      9             List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
     10             List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
     11                     new LinkedList<BeanDefinitionRegistryPostProcessor>();
     12 
     13             for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
     14                 // 特殊的BeanDefinitionRegistryPostProcessor的,比如处理@configuration.注册bd
     15                 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
     16                     BeanDefinitionRegistryPostProcessor registryPostProcessor =
     17                             (BeanDefinitionRegistryPostProcessor) postProcessor;
     18                     registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
     19                     registryPostProcessors.add(registryPostProcessor);
     20                 }
     21                 else {
     22                     regularPostProcessors.add(postProcessor);
     23                 }
     24             }
     25 
     26             // Do not initialize FactoryBeans here: We need to leave all regular beans
     27             // uninitialized to let the bean factory post-processors apply to them!
     28             // Separate between BeanDefinitionRegistryPostProcessors that implement
     29             // PriorityOrdered, Ordered, and the rest.
     30             String[] postProcessorNames =
     31                     beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     32 
     33             // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
     34             List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
     35             for (String ppName : postProcessorNames) {
     36                 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
     37                     priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     38                     processedBeans.add(ppName);
     39                 }
     40             }
     41             sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
     42             registryPostProcessors.addAll(priorityOrderedPostProcessors);
     43             invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
     44 
     45             // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
     46             postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     47             List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
     48             for (String ppName : postProcessorNames) {
     49                 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
     50                     orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     51                     processedBeans.add(ppName);
     52                 }
     53             }
     54             sortPostProcessors(beanFactory, orderedPostProcessors);
     55             registryPostProcessors.addAll(orderedPostProcessors);
     56             invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
     57 
     58             // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
     59             boolean reiterate = true;
     60             while (reiterate) {
     61                 reiterate = false;
     62                 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     63                 for (String ppName : postProcessorNames) {
     64                     if (!processedBeans.contains(ppName)) {
     65                         BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
     66                         registryPostProcessors.add(pp);
     67                         processedBeans.add(ppName);
     68                         pp.postProcessBeanDefinitionRegistry(registry);
     69                         reiterate = true;
     70                     }
     71                 }
     72             }
     73 
     74             // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
     75             invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
     76             invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
     77         }
     78 
     79         else {
     80             // Invoke factory processors registered with the context instance.
     81             invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
     82         }
     83 
     84         // Do not initialize FactoryBeans here: We need to leave all regular beans
     85         // uninitialized to let the bean factory post-processors apply to them!
     86         String[] postProcessorNames =
     87                 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
     88 
     89         // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
     90         // Ordered, and the rest.
     91         List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
     92         List<String> orderedPostProcessorNames = new ArrayList<String>();
     93         List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
     94         for (String ppName : postProcessorNames) {
     95             if (processedBeans.contains(ppName)) {
     96                 // skip - already processed in first phase above
     97             }
     98             else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
     99                 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    100             }
    101             else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    102                 orderedPostProcessorNames.add(ppName);
    103             }
    104             else {
    105                 nonOrderedPostProcessorNames.add(ppName);
    106             }
    107         }
    108 
    109         // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    110         sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    111         invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    112 
    113         // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    114         List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    115         for (String postProcessorName : orderedPostProcessorNames) {
    116             orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    117         }
    118         sortPostProcessors(beanFactory, orderedPostProcessors);
    119         invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    120 
    121         // Finally, invoke all other BeanFactoryPostProcessors.
    122         List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    123         for (String postProcessorName : nonOrderedPostProcessorNames) {
    124             nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    125         }
    126         invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    127     }
    View Code

    6.registerBeanPostProcessors(beanFactory);

    注册BPP.

    之前是BFPP用于处理BeanFactory,处理其中的BeanDifination.那这里就是注册BPP用于在处理bean了.

    对于BPP并没有手动注册的方法..比如ac的addBeanPostProcessor这种方法..BFPP相关方法的调用是先于bean 初始化(new)的,很好理解,因为是对BeanFactory的处理,而不是当bean的处理.. (但是BFPP也是会在bean new之前全部被扫描从bf里找出来特殊处理...所以从这点上说好像不用手动配置也可以..)

    而bpp是在bean 初始化或者填充属性过程中处理的.是在bean被new的过程中处理的...没必要手动注册...因为当前这一步仅仅是添加bpp..还不会调用bpp的相关方法(因为这个时候还没有new bean)...这一点BFPP不同(BFPP直接调用相关方法).直接和一般的bean一样配置就行了.

    BPP的处理顺序和BFPP一样(再次强调一下,这里只是把这些BPP的特殊的bean new出来了.并不会new 一般的bean.所以这里不会调用BPP的相关方法).最后就是BPP也有特殊的子接口,叫做MergedBeanDefinitionPostProcessor,是最后处理的.所以这些MergedBeanDefinitionPostProcessor会在BPP的最内层.(如果只是当做一般的BPP去使用相关方法的话就不要使用这个子接口.因为会影响处理的顺序..)

    7.initMessageSource

    初始化MessageSource,主要用于国际化.没怎么用过.没深入研究..大致是读取不同语言的properties根据Locale去做相应的处理.

    8.initApplicationEventMulticaster

    同7个人没咋用过.

    ApplicationContext可以publish一些Event.你也可以注册一些Listener去监听自己感兴趣的实践.

    9.onRefresh();

    也是一个模板方法.给子类ac一个机会去初始化自己想要初始化的特殊的bean

    比如一些web的ac会初始化ThemeSource...用于web页面的主题展示和切换...比如jsp里的标签:<spring:theme code="style"/>

    现在前后端分离了这个感觉很少用了...

    10.registerListeners();

    配合8.可以注册一些listener去监听你感兴趣的ApplicationEvent

    11.finishBeanFactoryInitialization(beanFactory);

    除了注册一些特殊的bean.比如ConversionService以外.

    最重要的就是对于之前BF加载的每一个BD.如果这个bean是单例并且不是lazy的.不是abstract的(XML里可以配置一个bean是abstract.用于继承简化配置),就去初始化对应的bean.也就是通过BeanFactory.doGetBean方法去创建这个bean的实例..

    里面涉及比较复杂的步骤...涉及各种BPP的调用,还有各种情况的处理...比如循环依赖, 代理方法什么的.....后面会再分享..

    12.finishRefresh()

    完成refresh.个人没怎么用过.

    会注册LifecycleProcessor.如果你的bean实现了Lifecycle接口.在ac做stop.refresh或者start等方法的时候你的bean也会被调用这些方法给你一些回调处理的机会.

     

  • 相关阅读:
    IDEA中源值1.5已过时,将在未来所有发行版中删除
    Spring带你飞(1)—— Spring概述
    2019 找钢网java面试笔试题 (含面试题解析)
    2019 百合佳缘java面试笔试题 (含面试题解析)
    2019 盛天网络java面试笔试题 (含面试题解析)
    2019 小红书java面试笔试题 (含面试题解析)
    2019 中至数据java面试笔试题 (含面试题解析)
    2019 创蓝253java面试笔试题 (含面试题解析)
    2019 东方网java面试笔试题 (含面试题解析)
    2019 第一视频java面试笔试题 (含面试题解析)
  • 原文地址:https://www.cnblogs.com/abcwt112/p/12388982.html
Copyright © 2011-2022 走看看