1. 详解Spring 中如何控制2个bean中的初始化顺序
开发过程中有这样一个场景,2个 bean 初始化逻辑中有依赖关系,需要控制二者的初始化顺序。实现方式可以有多种,本文结合目前对 Spring 的理解,尝试列出几种思路。
场景
假设A,B两个 bean 都需要在初始化的时候从本地磁盘读取文件,其中B加载的文件,依赖A中加载的全局配置文件中配置的路径,所以需要A先于B初始化,此外A中的配置改变后也需要触发B的重新加载逻辑,所以A,B需要注入彼此。
对于下面的模型,问题简化为:我们需要initA()先于initB()得到执行。
1.1 方案一:立Flag
可以在业务层自己控制A,B的初始化顺序,在A中设置一个“是否初始化的”标记,B初始化前检测A是否得以初始化,如果没有则调用A的初始化方法,所谓的check-and-act。对于上述模型,实现如下:
[站外图片上传中...(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中对应的初始化逻辑。
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()
代码如下:
容器在启动之前要获得对象锁,保证容器只有一个启动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():刷新前的预处理;
initPropertySources()
是初始化上下文环境,容器的一些信息这个时候加载了进来比如文件路径信息;getEnvironment().validateRequiredProperties()
查看标示为必填的属性信息是否都有了,校验配置文件的属性和合法性。
2.2 obtainFreshBeanFactory:实例化beanFactory
查看
refreshBeanFactory
,beanFactory
创造过程。继续追踪到AbstractApplicationContext
的子类:AbstractRefreshableApplicationContext
refreshBeanFactory:
- 先判断是否已经存在
BeanFactory
,如果存在,则销毁所有的bean,并关闭beanFactory
;防止重复加载beanFactory
; - 创建一个
beanFactory
(类型为DefalutListableBeanFactory
),最重要的BeanFactory
;spring注册及加载bean就靠它。其实这里还是一个基本的容器 - 初始化
XmlBeanDefinitionReader
用来读取xml,并加载解析 - 设置为全局变量,
AbstractRefreshableApplicationContext
持有DefaultListableBeanFactory
引用
customizeBeanFactory
,在类AbstractRefreshableApplicationContext
中,这里是根据AbstractRefreshableApplicationContext
类的属性为Beanfactory
设置值。
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中BeanFactoryPostProcessor
和BeanPostProcessor
都是Spring初始化bean时对外暴露的扩展点。两个接口从名字看起来很相似,但是作用及使用场景却不同。
Spring IoC容器允许BeanFactoryPostProcessor
在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义多个BeanFactoryPostProcessor
,通过设置'order'属性来确定各个BeanFactoryPostProcessor
执行顺序。
注册一个BeanFactoryPostProcessor
实例需要定义一个Java类来实现BeanFactoryPostProcessor
接口,并重写该接口的postProcessorBeanFactory
方法。通过beanFactory
可以获取bean的定义信息,并可以修改bean的定义信息。这点是和BeanPostProcessor
最大区别!
如下,Spring中bean工厂后置处理器也就是BeanFactoryPostProcessor
接口:
注释可知允许我们在工厂里所有的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
的代码,可以看出只有两个方法。
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);
}
}
}
2.10 finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例bean
在完成BeanFactory
初始化之时,会初始化容器内所有单例非懒加载对象,供后续业务逻辑进行依赖注入等使用,具体实现在finishBeanFactoryInitialization(beanFactory)
内部的最后一行代码:
// 预实例化所有非懒加载单例Bean
beanFactory.preInstantiateSingletons();
具体的preInstantiateSingletons
实现如下:
如上所示代码:
beanNames = new ArrayList<String>(this.beanDefinitionNames);
- 获取容器内加载的所有BeanDefinition
for (String beanName : beanNames)
- 遍历初始化所有非懒加载单例Bean
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
- Bean定义公共的抽象类是
AbstractBeanDefinition
,普通的Bean在Spring加载Bean定义的时候,实例化出来的是GenericBeanDefinition
- 而Spring上下文包括实例化所有Bean用的
AbstractBeanDefinition
是RootBeanDefinition
- 这时候就使用
getMergedLocalBeanDefinition
方法做了一次转化,将非RootBeanDefinition
转换为RootBeanDefinition
以供后续操作。 - 注意如果当前
BeanDefinition
存在父BeanDefinition
,会基于父BeanDefinition
生成一个RootBeanDefinition
,然后再将调用OverrideFrom子BeanDefinition
的相关属性覆写进去。
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
- 如果Bean不是抽象的,是单例的,不是懒加载的,则开始创建单例对象通过调用getBean(beanName)方法初始化
具体getBean函数实现如下所示:
[站外图片上传中...(image-a39a5e-1551843463104)]
进一步调用了如下方法,其中有参数:
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);
- 根据名字获取合并过的对应的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