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也会被调用这些方法给你一些回调处理的机会.

     

  • 相关阅读:
    METHODS OF AND APPARATUS FOR USING TEXTURES IN GRAPHICS PROCESSING SYSTEMS
    Display controller
    Graphics processing architecture employing a unified shader
    Graphics-Processing Architecture Based on Approximate Rendering
    Architectures for concurrent graphics processing operations
    Procedural graphics architectures and techniques
    DYNAMIC CONTEXT SWITCHING BETWEEN ARCHITECTURALLY DISTINCT GRAPHICS PROCESSORS
    Thermal zone monitoring in an electronic device
    System and method for dynamically adjusting to CPU performance changes
    Framework for Graphics Animation and Compositing Operations
  • 原文地址:https://www.cnblogs.com/abcwt112/p/12388982.html
Copyright © 2011-2022 走看看