Spring容器中Bean的创建
测试代码
<bean id="user" class="com.sanfen.entity.User">
<property name="id" value="100"/>
<property name="name" value="2233"/>
<property name="age" value="27"/>
</bean>
public class SpringDemo {
public static final Logger logger = LoggerFactory.getLogger(SpringDemo.class);
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("user");
logger.info("user对象: [{}]", user);
}
}
探究目标
我们在Spring中配置好bean之后,就可以通过bean的名称或者Class获取bean对象。现在想知道,这个bean是在什么时候创建的
?bean是怎么创建
的?
bean是在什么时候被创建的
这个比较简单,我们写的代码就几行。可以发现第一行是处理spring的配置文件,第二行是获取bean。debug调试,看是在哪一行代码创建的。

执行这行代码,看User
有没有被创建:

由此,可以得出结论。
Spring中的bean是在加载配置文件的时候创建的,之后通过getBean直接获取这个创建的bean。
bean是怎么创建的
现在,我们可以进入源码,看看bean具体是怎么创建的。也不必看得很深,看到我们熟悉的代码就行了。也不用每行代码都看,关注主要的部分:bean的创建
。
1.进入
ClassPathXmlApplicationContext
。接下来是refresh()方法
。
我们可以通过执行这行代码之后,查看容器中有没有对应的bean。来发现具体的执行代码。通过调试,我们发现。执行完refresh()
之后,User
被创建了。关键代码在这里:

2.进入
AbstractApplicationContext
。这个类里面的refresh()
是最关键的,几乎整个bean的生命周期的代码都在这里,我们这次只关注bean的创建。

进入finishBeanFactoryInitialization()
方法:

3.进入
DefaultListableBeanFactory
。

可以发现这里有个集合beanDefinitionNames
,里面存储了bean的名字。接下来是实例化bean:

循环体内,首先会根据bean的名称获取到BeanDefinition
,这个我们先看看里面有什么东西:

可以发现,这个BeanDefinition
就是我们在Spring配置文件中配置的bean标签。这里把xml文件里面的配置转换成了BeanDefinition
对象的属性。可以猜测,后面会根据这个配置对象生成bean。BeanDefinition
是很重要的,它包含了bean的定义信息。不过这次我们不关注,我们主要看bean是怎么创建的。往下看:

因为我们是默认配置,所以没有走FactoryBean
的逻辑。FactoryBean
也是重点,这次也不关注。再往下看。
4.进入
AbstractBeanFactory
。

doGetBean()
方法:
首先获取bean的名字:

接下来是一堆的检查判断,走到关键代码:

进入createBean()
方法:

5.进入
AbstractAutowireCapableBeanFactory
的createBean()
。
找到关键代码:

进入doCreateBean()
:

接下来获取bean的类型:

这里我们可以得出一个结论:bean的实例化是先创建空对象,然后再填充属性。
再往下走,可以发现这里提到了循环引用:

接下里是填充bean的属性:

调用applyPropertyValues()
方法:

深拷贝填充属性:

BeanWrapper设置属性:

属性填充完毕。会放到对应的BeanDefinition
中。接下里进行bean的初始化。

AbstractAutowireCapableBeanFactory
中。也可以发现,之前的对象属性有了值:

进入initializeBean()
方法,通过bean名称
,bean对象
,BeanDefinition
进行bean的初始化。

首先会填充Aware接口相关的资源:

接下里进行bean的初始化方法调用,而且在bean的初始化方法前后都会调用bean后置处理器。

由此我们可以得出结论:
bean的创建有这几个步骤:
- 首先会创建实例,然后再填充这个实例的属性。
- 如果实现了Aware接口,会填充对应的资源。
- 调用bean的初始化方法,并且调用初始化方法前后都会调用bean的后置处理器。bean的初始化方法是指bean在创建之后调用的方法。比如实现
InitializingBean/DisposableBean
接口
doCreateBean()
方法中,接下来继续往下走:

接下进行返回。
6.
AbstractAutowireCapableBeanFactory
中。

7.进入
DefaultSingletonBeanRegistry
的getSingleton()
方法:

进入addSingleton()方法
:

到了这里,发现Spring把创建的单例bean放入了一个HashMap中。key是bean的名称,value是bean对象。我们是可以通过bean的名称获取到bean。到这里就明白为什么能获取到了。就是对HashMap的操作。只不过Spring在把bean对象放入Map之前,做了大量的工作。
8.返回到
AbstractBeanFactory
中。

接下来Spring还会做相关的工作来保证bean的正常使用。
9.返回到
DefaultListableBeanFactory
。这时,容器中已经有了bean。

10.返回到
AbstractApplicationContext
中。

bean的创建就完成了。

总结
bean的创建关键方法是
AbstractApplicationContext
中的refresh()
方法。这里定义了bean的整个生命周期的代码。@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. 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) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
首先会根据spring配置文件获取到bean的定义信息,并存储到
BeanDefinition
对象。接下来会先判断是不是
FactoryBean
,FactoryBean
有自己的处理逻辑。普通bean会根据beanName获取。bean的实例化是先创建空对象,然后再填充属性,使用的是深拷贝填充属性。其中会涉及到循环引用。
Spring通过
bean名称
,bean对象
,BeanDefinition
进行bean的初始化。首先会填充Aware接口相关的资源。接下里进行bean的初始化方法调用,而且在bean的初始化方法前后都会调用bean后置处理器。
Spring最终把创建的单例bean放入了一个
HashMap
中。key是bean的名称,value是bean对象。我们是可以通过bean的名称获取到bean。