Spring IOC 初始化有很多种方式,如 xml 方式、注解方式(也分很多不同的方式)、FactoryBean 方式等等,这个在之前的博客中有写过(原文:Spring IOC 初始化 bean 对象创建的 N 种实现方式理解)。这里就其中的一种方式来理解一下整个创建 bean 的基本过程。
1. 前提说明
在写之前,先说明一下场景。
- 这里是从
AnnotationConfigApplicationContext
的构造方法进入。当然进入的还有很多其他方式,如ClassPathXmlApplicationContext
等。他们的共同点都是继承与ApplicationContext
。 - 这里只做基本的说明,至于代理对象生成考虑、后置处理器的工作机制,多例的情况下如何运作,以后的博客会慢慢的来分析,这里解释的是单例非懒加载实例的初始化过程。
- 另外在贴出的源代码中,使用省略号将部分代码替代,否则代码过多反而影响对源代码的理解。
2. 源码分析
在做 IOC 容器初始化的时候,采用下面的方式:
ApplicationContext app = new AnnotationConfigApplicationContext(InitDemo.class);
进入到上面AnnotationConfigApplicationContext(clazz)
的构造方法中,源码如下:
/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();//调用无参构造方法
register(annotatedClasses);//注册Configuration配置类(可能有多个)
refresh();//刷新方法
}
2.1 refresh()
进入到AbstractApplicationContext
类中看refresh()
方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 刷新前的预处理,如environment环境信息、自定义环境信息的加入
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 创建IOC容器bean工厂(beanFactory)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// bean工厂(beanFactory)的预处理,属性的设置等操作
// 上一步创建的beanFactory内属性基本都是没有值或者是默认值
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 没有逻辑实现,空方法,可以通过实现BeanFactoryProcessor,重写该方法,自定义逻辑
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/*
* 工厂processor处理器定义和所有bean的定义
* 自定义bean包含单例bean、多例bean、懒加载bean
* bean的定义在processor处理器定义的之前执行
* 等待后续的实例化使用
* 这一步必须在单例非懒加载bean初始化之前完成
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// bean实例化过程拦截的processor处理器,并注册到beanFactory中
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化标签国际化
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 可通过继承,实现此方法,做个性化操作
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化单例实例(非懒加载)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
//……
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
这个方法包含很多东西,前面一系列的方法调用都是为后续的单例非懒加载 bean 的初始化做准备。
- bean 工厂的 beanFacotry 的实例化以及其内部属性的初始化
- bean 创建过程使用到处理器(processor)的前置处理和后置处理,所以这里需要在 bean 创建逻辑开始之前,将所有的处理器初始化完成
2.2 finishBeanFactoryInitialization()
进入到AbstractApplicationContext
类中finishBeanFactoryInitialization()
方法里面。
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
* 完成上下文bean工厂的初始化
* 初始化所有的单例bean
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 核心方法:初始化单例bean(非懒加载bean)
beanFactory.preInstantiateSingletons();
}
这个方法已经说明很清楚,是用来做 bean 工厂的初始化和单例非懒加载 bean 的初始化,以及加入到容器中。到这里说 bean 工厂的初始化可能会觉得在refresh()
方法中不是已经完成了吗。但是那只是 bean 工厂的初期初始化,后期装配好的 bean 也是要丢入到 bean 工厂里面,也属于 bean 工厂初始化的一部分。
2.3 preInstantiateSingletons()
进入DefaultListableBeanFactory
类中preInstantiateSingletons()
方法看具体的 bean 实例化过程。
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
//代码1:尝试到本地获取bean,也就是从bean工厂里获取,bean工厂首次加载,这里获取的bd坑定为null
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
/*
*判断bd的属性
* isAbstract:是否是抽象类,抽象类是不能实例化的
* isSingleton:是否是单例
* isLazyInit:是否是懒加载
*/
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) { //判断是否实现了FactoryBean接口
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);//获取bean
}
}
else {
getBean(beanName);//获取bean
}
}
}
// ……
获取当前所有要初始化的 bean 并遍历,进入到循环中后,首先是判断有没有实现FactoryBean
接口,根据不同的时间执行不同的getBean
逻辑,这里以没有实现FactoryBean
接口的实例化过程为主线。
2.4 getBean()、doGetBean()
进入第二个getBean()
方法。getBean()
方法中就一行代码。
return doGetBean(name, null, null, false);
此处无书,进入AbstractBeanFactory
类中doGetBean()
方法。
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 获取单例bean,初始化过程,不会有bean存在,返回为null
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// ……
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//使用RootBeanDefinition对当前bean的信息进行封装
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// ……
// Create bean instance.
// 核心:创建bean实例
if (mbd.isSingleton()) {
// 从这里进入到getSingleton()方法,这里需要留意createBean()方法
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// ……
}
else {
// ……
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// ……
return (T) bean;
}
主要的代码都加了注释,这个方法里面其实核心的就三步,第一是尝试从容器中获取 bean,如果获取到直接返回,获取不到进入第二步,使用RootBeanDefinition
来封装当前 bean 的信息。第三步创建 bean 实例,并将 bean 实例加入到 bean 工厂中。
2.5 getSingleton()
进入getSingleton()
方法。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
/*
* 创建bean前的判断,里面的代码很简单
* 第一是判断创建bean检查集合是否包含当前的beanName
* 第二是加入到当前正在创建的集合中是否成功
*/
beforeSingletonCreation(beanName);
// 设置是否为新单例bean的标记默认值为false
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 核心:调用创建单例bean的方法,也就是上一步lambda表达式内createBean方法
singletonObject = singletonFactory.getObject();
// 将是否为新单例bean的标记值设置为true
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//判断和beforeSingletonCreation类似
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 将新创建的bean添加到缓存中
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
在beforeSingletonCreation()
方法中,做了一下两个判断:
!this.inCreationCheckExclusions.contains(beanName)
,当前需要创建的 bean 集合中是否存在当前的这个 beanName,这个可以有效的保证当前创建为第一次创建;!this.singletonsCurrentlyInCreation.add(beanName)
,将当前的 beanName 加入到当前正在创建的 bean 集合中。
这两个条件就保证当前没有其他位置正在创建这个 bean,并将 bean 设置到正在创建的 bean 集合中,保证其他位置来创建的时候,能够得到有效的判断结果。
有 before 就有 after,这里的afterSingletonCreation()
前半段判断和beforeSingletonCreation()
相同,但是后半段是将当前的 beanName 从 bean 集合中移除。
在addSingleton()
方法中,就是将当前创建的对象放入到对象缓存中,并将当前 bean 的起初需要注册的信息和起初 bean 封装信息移除。这些信息是用来为 bean 创建而存在的,待 bean 创建成功键入缓存中后,这个信息自然就会被移除。
2.6 createBean()
上面的创建前、后方法以及加入到缓存中的方法都已经解释,接下来要看一下核心方法createBean()
,在AbstractAutowireCapableBeanFactory
类中。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// ……
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
/*
* 给一次尝试获取代理对象的机会,这里如果采用debug进入的话,可以看出返回的都是空
* 可能只会在特殊的场景下才会得到对应的结果,这里忽略
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 核心:调用创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
这个方法里面主要需要注意的是具有迷惑性的resolveBeforeInstantiation()
,这里可以忽略。接下里进入到doCreateBean()
方法,还是在AbstractAutowireCapableBeanFactory
类中。
2.7 doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// 实例化当前的bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//使用BeanWrapper对象封装当前需要创建的bean对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//……
// Initialize the bean instance.
// 初始化bean实例
Object exposedObject = bean;
try {
// 属性初始化
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 核心:初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//……
return exposedObject;
}
这里分为两个部分,一个是使用BeanWrapper
封装 bean,然后通过populateBean()
方法填充 bean 的数据信息。
2.8 initializeBean()
进入到initializeBean()
方法中。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//……
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 处理器的前置处理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 处理器的后置处理方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这里最主要的方法就是处理器的前置处理,处理器的后置处理,一般对于基本 bean 的创建来说,前置处理没有太多的逻辑,主要是在后置处理里面,这个时候整个 bean 完成了全部的初始化,可以通过后置来对 bean 对象进行增强,常见的有 AOP 切面增强,生成代理对象等。
3. 图例分析
上面说的内容很多,涉及到很多方法的跳转,可能会比较乱,通过下面的这个流程图,可以有更深入的了解。
通过这个流程图,加上对上面内容的理解,其实整个过程就是创建 IOC 容器,然后遍历初始化 bean,然后将初始化后的 bean 丢入到容器中。相信通过上面的说明你对 Spring IOC 初始化过程有所了解。
但是上面源码分析的过程还少一步,但是图里面已经体现出来了,那就是getSingleton()
方法的最后,会将新创建的 bean 放到 IOC 容器中,调用的方法是addSingleton()
。看一下源码:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 这里就是将创建完成的bean实例SingletonObject放入到容器中
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
从this.singletonObjects.put()
方法中可以看出来,容器中存放 bean 是通过 Map 集合,但是需要注意的是这里的 bean 不是裸着的真正 bean,而是通过封装后的封装 bean。(后期更新 bean 实例的获取、以及 FactoryBean 和 BeanFactory 区别的时候,理解起来就可以更清晰)。
//singletonObjects存储bean的Map集合
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
到这里真个 IOC 的加载过程主流程基本都说完了,但是还存在很多细枝末节的东西(比如多例是怎么实现的,懒加载又是怎么做的,增强的代理对象生成的过程等等),后续的文章还慢慢道来。