Spring装配Bean--源码学习

1. 详解Spring 中如何控制2个bean中的初始化顺序

  开发过程中有这样一个场景,2个 bean 初始化逻辑中有依赖关系,需要控制二者的初始化顺序。实现方式可以有多种,本文结合目前对 Spring 的理解,尝试列出几种思路。
场景
假设A,B两个 bean 都需要在初始化的时候从本地磁盘读取文件,其中B加载的文件,依赖A中加载的全局配置文件中配置的路径,所以需要A先于B初始化,此外A中的配置改变后也需要触发B的重新加载逻辑,所以A,B需要注入彼此。
对于下面的模型,问题简化为:我们需要initA()先于initB()得到执行。

image

1.1 方案一:立Flag

  可以在业务层自己控制A,B的初始化顺序,在A中设置一个“是否初始化的”标记,B初始化前检测A是否得以初始化,如果没有则调用A的初始化方法,所谓的check-and-act。对于上述模型,实现如下:

image

[站外图片上传中...(image-a48682-1551843463104)]
执行效果:

A construct
B construct
A init
B init

  这种立flag的方法好处是可以做到lazy initialization,但是如果类似逻辑很多的话代码中到处充斥着类似代码,不优雅,所以考虑是否框架本身就可以满足我们的需要。

1.2 方案二:使用DependsOn

  Spring 中的 DependsOn 注解可以保证被依赖的bean先于当前bean被容器创建,但是如果不理解Spring中bean加载过程会对 DependsOn 有误解;

1.3方案三:容器加载bean之前

  Spring 框架中很多地方都为我们提供了扩展点,很好的体现了开闭原则(OCP)。其中 BeanFactoryPostProcessor 可以允许我们在容器加载任何bean之前修改应用上下文中的BeanDefinition(从XML配置文件或者配置类中解析得到的bean信息,用于后续实例化bean)。

  在本例中,就可以把A的初始化逻辑放在一个 BeanFactoryPostProcessor 中。
[站外图片上传中...(image-8c8fa4-1551843463104)]

执行效果:

A init
A construct
B construct
B init

  这种方式把A中的初始化逻辑放到了加载bean之前,很适合加载系统全局配置,但是这种方式中初始化逻辑不能依赖bean的状态。

1.4 方案四:事件监听器的有序性

  Spring 中的 Ordered 也是一个很重要的组件,很多逻辑中都会判断对象是否实现了 Ordered 接口,如果实现了就会先进行排序操作。比如在事件发布的时候,对获取到的 ApplicationListener 会先进行排序。
所以可以利用事件监听器在处理事件时的有序性,在应用上下文 refresh 完成后,分别实现A,B中对应的初始化逻辑。

image
image

2. Spring装配Bean的过程

   Spring装配Bean的过程

1. 实例化;
2. 设置属性值;
3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;
4. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;
5. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext
6. 调用BeanPostProcessor的预先初始化方法;
7. 调用InitializingBean的afterPropertiesSet()方法;
8. 调用定制init-method方法;
9. 调用BeanPostProcessor的后初始化方法;

分析:
spring的两个核心接口BeanFactory和ApplicationContext。BeanFactory主要定义容器的核心方法,ApplicationContext加以扩展,主要使用的还是ApplicationContext。在ApplicationContext的子类中,AbstractApplicationContext中的refresh()方法定义了容器加载配置文件及装配Bean的过程。
AbstractApplicationContext#refresh()代码如下:

image

容器在启动之前要获得对象锁,保证容器只有一个启动synchronized

/容器在启动之前要获得对象锁,保证容器只有一个启动synchronized

//1 准备刷新工作,刷新前的预处理
prepareRefresh();

// 2 实例化BeanFactory,将配置文件的信息装入到容器的Bean定义的注册表(BeanDefinitionRegistry中),此时Bean还未初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 3 准备BeanFactory 主要是加载一些类,
prepareBeanFactory(beanFactory);
try {
    // 4 留作子类实现
    //抽象的方法,当前未做处理。子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
    postProcessBeanFactory(beanFactory);
    /*******以上是BeanFactory的创建及预准备工作*****/
        
    // 5 调用工厂后处理器
    invokeBeanFactoryPostProcessors(beanFactory);
    
    //6 注册bean后处理器,注册BeanPostProcessor(Bean的后置处理器)
    registerBeanPostProcessors(beanFactory);
    
    //7 初始化消息源,初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
    initMessageSource();
    
    //8 初始化事件广播器
    initApplicationEventMulticaster();
    
    //9 钩子方法
    onRefresh();
    
    // 10 注册监听器,给容器中将所有项目里面的ApplicationListener注册进来
 
    registerListeners();
    
    //11 完成bean实例化(除lazy-init),并放入缓存中,
    //   初始化所有剩下的单实例bean;
    finishBeanFactoryInitialization(beanFactory);
    
    // 12 广播刷新事件,完成BeanFactory的初始化创建工作;IOC容器就创建完成;
    finishRefresh();
}

refresh()函数的重点步骤:

2.1 prepareRefresh():刷新前的预处理;

image

  initPropertySources()是初始化上下文环境,容器的一些信息这个时候加载了进来比如文件路径信息;getEnvironment().validateRequiredProperties()
查看标示为必填的属性信息是否都有了,校验配置文件的属性和合法性。

2.2 obtainFreshBeanFactory:实例化beanFactory

image

  查看refreshBeanFactorybeanFactory创造过程。继续追踪到AbstractApplicationContext的子类:
AbstractRefreshableApplicationContext
  refreshBeanFactory

  1. 先判断是否已经存在BeanFactory,如果存在,则销毁所有的bean,并关闭beanFactory;防止重复加载beanFactory
  2. 创建一个beanFactory(类型为DefalutListableBeanFactory),最重要的BeanFactory;spring注册及加载bean就靠它。其实这里还是一个基本的容器
  3. 初始化XmlBeanDefinitionReader用来读取xml,并加载解析
  4. 设置为全局变量,AbstractRefreshableApplicationContext持有DefaultListableBeanFactory引用
image

customizeBeanFactory,在类AbstractRefreshableApplicationContext中,这里是根据AbstractRefreshableApplicationContext类的属性为Beanfactory设置值。

image

allowBeanDefinitionOverriding属性是指是否允对一个名字相同但definition不同进行重新注册,默认是true。 allowCircularReferences属性是指是否允许Bean之间循环引用,默认是true.
默认情况下两个属性都为空,既然是可扩展的,那么自然可以自己设置属性,方法就是继承ClassPathXmlApplicationContext并复写customizeBeanFactory方法为两个属性设置值即可。

2.3 prepareBeanFactory:BeanFactory的预准备工作

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 1)、设置BeanFactory的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 1)、设置支持表达式解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
​
    // 2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 3)、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
   // 这些接口的实现类不能通过类型来自动注入
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
​
    // 4)、注册可以解析的自动装配;我们能直接在任何组件中自动注入:
    //BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
    /* 其他组件中可以通过下面方式直接注册使用
    @autowired 
    BeanFactory beanFactory */
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
​
    // 5)、添加BeanPostProcessor【ApplicationListenerDetector】后置处理器,在bean初始化前后的一些工作; 
    // 将当前的ApplicationContext对象交给ApplicationContextAwareProcessor类来处理,从而在Aware接口实现类中的注入applicationContext

    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
​
    // 6)、添加编译时的AspectJ;
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
​
    // 7)、给BeanFactory中注册一些能用的组件;
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    // 环境信息ConfigurableEnvironment
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    //系统属性,systemProperties【Map<String, Object>】
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    //系统环境变量systemEnvironment【Map<String, Object>】
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

总结:

 1.设置类加载器;
 2.设置EL表达式解析器(Bean创建完成填充属性时使用)和属性注册解析器
 3.利用BeanPostProcessor的特性给各种Aware接口的实现类注入ApplicationContext中对应的属性
 4.设置各种Aware接口的实现类为忽略自动装配
 5.设置自动装配的类(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext)
 6.如果BeanFactory中存在loadTimeWeaver的bean,那么需要添加动态织入功能
 7.注册各种可用组件(environment,systemProperties,systemEnvironment)

2.4 执行BeanFactoryPostProcessor的后置处理器方法(BeanFactory)

  Spring中BeanFactoryPostProcessorBeanPostProcessor都是Spring初始化bean时对外暴露的扩展点。两个接口从名字看起来很相似,但是作用及使用场景却不同。
  Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义多个BeanFactoryPostProcessor,通过设置'order'属性来确定各个BeanFactoryPostProcessor执行顺序。

   注册一个BeanFactoryPostProcessor实例需要定义一个Java类来实现BeanFactoryPostProcessor接口,并重写该接口的postProcessorBeanFactory方法。通过beanFactory可以获取bean的定义信息,并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别!
如下,Spring中bean工厂后置处理器也就是BeanFactoryPostProcessor接口:

image

  注释可知允许我们在工厂里所有的bean被加载进来后但是还没初始化前,对所有bean的属性进行修改也可以add属性值。
注意:
BeanFactoryPostProcessor可以与bean definitions打交道,但是千万不要进行bean实例化(感觉这里应该说的是不要在BeanFactoryPostProcessor进行可能触发bean实例化的操作)。这么做可能会导致bean被提前实例化,会破坏容器造成预估不到的副作用。如果你需要hack到bean实例化过程,请考虑使用BeanPostProcessor

  definitions进行一定hack,但是也仅此而已了。绝对不允许在BeanFactoryPostProcessor中触发到bean的实例化!!!
doc说得很清楚but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects. 下面就列举错误使用造成的两种典型“副作用”。

错误1)使用注解进行依赖注入失败


@Component
public class PrematureBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, BBean> map = beanFactory.getBeansOfType(BBean.class);
        for (BBean bBean : map.values()) {
            assert bBean.getABean() == null;
        }
    }
}

@Component("bBean")
public class BBean {

    @Autowired
    private ABean aBean;

    public ABean getABean() {
        return aBean;
    }

}

@Component
public class ABean {

    private String name = "a";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

  从装配bean的AbstractApplicationContext#refresh()方法中可以看到的是postProcessBeanFactory(beanFactory); 首先invoke了容器中的BeanFactoryPostProcessor实现类,其中当然就包括PrematureBeanFactoryPostProcessor,此时通过beanFactory.getBeansOfType触发了bean提前实例化。
  按理说,bean提前实例化也应该没问题的,aBean也应该是能够被注入的呀!那为啥最终不是这个结果呢。让我们研究下@Resource @AutoWired这种注解是如何注入依赖的,如何起作用的就明白了。
@AutoWired起作用依赖AutowiredAnnotationBeanPostProcessor, @Resource依赖CommonAnnotationBeanPostProcessor;
这俩都是BeanPostProcessor的实现。那BeanPostProcessors在何处被spring invoke呢,参见registerBeanPostProcessors(beanFactory);postProcessBeanFactory(beanFactory); 后面被调用,也就是说BBean被触发提前初始化的时候,AutowiredAnnotationBeanPostProcessor还没有被注册自然也不会被执行到,自然ABean=null

Spring的BeanPostProcessor和BeanFactoryPostProcessor区别
BeanPostProcessor:bean级别的处理,针对某个具体的bean进行处理,bean实例化之后执行;能在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑
BeanFactoryPostProcessor:是针对bean容器的,它的实现类可以在当前BeanFactory初始化(spring容器加载bean定义文件)后,bean实例化之前修改bean的定义属性,达到影响之后实例化bean的效果。BeanFactory级别的处理,是针对整个Bean的工厂进行处理,bean实例化之前执行;Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。

2.5 registerBeanPostProcessors:注册BeanPostProcessor(Bean的后置处理器)

registerBeanPostProcessors从名称可以看出是用来注册BeanPostProcessor的。下面是BeanPostProcessor的代码,可以看出只有两个方法。

BeanPostProcessor接口方法

postProcessBeforeInitialization作用:在bean实例化、依赖注入之后,初始化(显示)之前执行。什么叫显示初始化?我们知道在bean实例化之前,已经初始化对象了,这里显示指的是,要给bean的某些属性手动赋值,或手动去执行的某些方法。比如:init-method方法,其就是在实例化之后调用的。

postProcessAfterInitialization作用:在bean实例化、依赖注入之后,初始化(显示)之后执行。

上面讲到的BeanFactoryPostProcessor是用来处理bean工厂或者是bean定义的,BeanPostProcessor是用来处理bean实例的

public static void registerBeanPostProcessors(
    ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//1)、获取所有的 BeanPostProcessor;后置处理器都默认可以通过PriorityOrdered、Ordered接口来执行优先级
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
​
     //检查器,检查所有的BeanPostProcessor
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
​
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
​
  /*  2)、先注册PriorityOrdered优先级接口的BeanPostProcessor;
            把每一个BeanPostProcessor;添加到BeanFactory中
            beanFactory.addBeanPostProcessor(postProcessor);*/
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
​
    // 3)、再注册Ordered接口的
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
​
    // 4)、最后注册没有实现任何优先级接口的
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
​
    // 5)、最终注册MergedBeanDefinitionPostProcessor;
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
​
    // 6)、注册一个ApplicationListenerDetector;判断创建完成的bean是否监听器
   /* 在Bean创建完成后ApplicationListenerDetector.postProcessAfterInitialization()中检查是否是ApplicationListener 类型,如果是applicationContext.addApplicationListener((ApplicationListener<?>) bean);如果是添加到容器中 */
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

2.6 initMessageSource();国际化

初始化MessageSource组件(做国际化功能;消息绑定,消息解析);

protected void initMessageSource() {
  // 1)、获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    /*  
    2)、看容器中是否有id为messageSource的,类型是MessageSource的组件
            如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource;
            MessageSource作用:取出国际化配置文件中的某个key的值;能按照区域信息获取;
    */
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // Make MessageSource aware of parent MessageSource.
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // Only set parent context as parent MessageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // 如果没有自己创建一个DelegatingMessageSource;
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        //把创建好的messageSource注册到容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource; 
       //注入后通过这个方法使用MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale);
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                         "': using default [" + this.messageSource + "]");
        }
    }
}

2.7 初始化事件派发器initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {
    //1)、获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //判断容器中是否有applicationEventMulticaster 的这个bean ,如果有获取,没有创建
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        //2)、从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster;
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        //3) 个SimpleApplicationEventMulticaster 类型的 applicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        //4)、将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                         "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

2.8 onRefresh();留给子容器(子类)

类重写AbstractApplicationContext.onRefresh()这个方法,在容器刷新的时候可以自定义逻辑;

2.9 registerListeners();检查和注册 Listener

将所有项目里面的ApplicationListener注册到容器中;

protected void registerListeners() {
    //1、从容器中拿到所有的ApplicationListener
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        //2、将每个监听器添加到事件派发器中;
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    
    // 1.获取所有的ApplicationListener
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        //2、将每个监听器添加到事件派发器中;
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
​
    // earlyApplicationEvents 中保存之前的事件,
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
           //3、派发之前步骤产生的事件;
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}
image

2.10 finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例bean

在完成BeanFactory初始化之时,会初始化容器内所有单例非懒加载对象,供后续业务逻辑进行依赖注入等使用,具体实现在finishBeanFactoryInitialization(beanFactory)内部的最后一行代码:

// 预实例化所有非懒加载单例Bean
beanFactory.preInstantiateSingletons();

具体的preInstantiateSingletons实现如下:

image

image

如上所示代码:

beanNames = new ArrayList<String>(this.beanDefinitionNames);

  • 获取容器内加载的所有BeanDefinition
    for (String beanName : beanNames)
  • 遍历初始化所有非懒加载单例Bean

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

  • Bean定义公共的抽象类是AbstractBeanDefinition,普通的Bean在Spring加载Bean定义的时候,实例化出来的是GenericBeanDefinition
  • 而Spring上下文包括实例化所有Bean用的AbstractBeanDefinitionRootBeanDefinition
  • 这时候就使用getMergedLocalBeanDefinition方法做了一次转化,将非RootBeanDefinition转换为RootBeanDefinition以供后续操作。
  • 注意如果当前BeanDefinition存在父BeanDefinition,会基于父BeanDefinition生成一个RootBeanDefinition,然后再将调用OverrideFrom子BeanDefinition的相关属性覆写进去。

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())

  • 如果Bean不是抽象的,是单例的,不是懒加载的,则开始创建单例对象通过调用getBean(beanName)方法初始化

具体getBean函数实现如下所示:
[站外图片上传中...(image-a39a5e-1551843463104)]

进一步调用了如下方法,其中有参数:

image

image

image

final String beanName = transformedBeanName(name);

  • 如果是FactoryBean,会去掉Bean开头的&符号;
  • 可能存在传入别名且别名存在多重映射的情况,这里会返回最终的名字,如存在多层别名映射A->B->C->D,传入D,最终会返回A

Object sharedInstance = getSingleton(beanName);

  • 根据beanName从缓存中获取Bean ;从缓存中获取BeanInstance,根据不同的情况这个Bean实例做处理,或直接返回,
  • 这里先尝试从缓存中获取,获取不到再走后面创建的流程
  • 获取到有两种情况,一种是Bean创建完成存储到最终的缓存中。
  • 另一种是未创建完成,但先预存到一个单独的缓存中,这种是针对可能存在循环引用的情况的处理。

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

  • 这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例。真正的bean 返回处理

if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }

  • 原型对象不允许循环创建,如果是原型对象则抛异常
  • 假设循环依赖的时候,如果我们已经开始在当前线程中创建此bean实例,但是还没有创建完成,则失败;
  • 例如此时是A依赖于B,但是B不依赖于A,B也没有任何属性依赖于A,则不存在循环依赖,那么无论B初始化,未初始化都不会有以下情况。但是如果B依赖于A,A在获取依赖的Bean是激活创建B的方法,那么B创建过程中就会出现以下情况。就会出现循环依赖错误。如果A,B 是单例的并且A的构造函数不包含B,B的构造函数不包含A,spring还是可以通过提前暴露实例地址处理这种依赖,但是其它情况spring也无能为力了。

BeanFactory parentBeanFactory = getParentBeanFactory();

  • 获取父bean工厂

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
return parentBeanFactory.getBean()

  • 如果存在父bean工厂并且没有配置该bean,则从父bean工厂创建

markBeanAsCreated(beanName);

  • 进行已创建标记

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

image
  • 根据名字获取合并过的对应的RootBeanDefinition
  • 获取缓存的BeanDefinition对象并合并其父类和本身的属性。
  • 上面初始化得到的Bean的BeanDefinition用上
  • 转换BeanDefinition

String[] dependsOn = mbd.getDependsOn();

  • 获取依赖的Bean
  • 确保当前Bean依赖的相关Bean先完成初始化工作
  • depends-on标签;depend-on用来表示一个Bean的实例化依靠另一个Bean先实例化

if (mbd.isSingleton()) {

  • 开始创建Bean实例了,如果是单例的,那么会创建一个单例的匿名工厂

else if (mbd.isPrototype()) {

  • 原型模式 ,则不需要创建单例的工厂
1.singleton模式通过getSingleton方法,这个里面创建对象时会先校验缓存是 否已经存在该对象;
2.prototype模式直接创建对象,
3.其他类型的则可以通过自定义Scope来实现逻辑控制,
  设想一下如果把对象放到第三方缓存中则可在这边自定义一个Scope。
  最终bean的构造委托给了createBean
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容

  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,626评论 0 11
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,906评论 4 21
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,739评论 1 24
  • 今天熬过去就一周啦~ 一日三餐 早 半个梨 半个芒果 一个麦片 一杯酸奶三个枣 一个鸡蛋(怎么感觉我在增肥。。。)...
    木青就是我阅读 279评论 0 0
  • 人生有那么多的细节 让我们乎略 使诸多的可能 付诸东流。 人生有那么多的毫离 使成功渐行渐远, 成为暮然回首。 别...
    泰康人寿诗人阅读 287评论 5 3