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。