上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对IoC容器启动方法也就是refresh()
方法的简单分析。但是之前的分析在对容器实例化Bean的过程的略过了,留到了这后续的文章分析,所以这篇文章会对Bean的实例化过程做一个介绍。
首先来理一下本文的思路:关键词是实例化。由于Spring是利用反射实现的实例化,脑子里先简单想一下Java里利用发射实例化一个对象需要哪些步骤和操作。毫无疑问,我们首先要知道对象的class
,接着需要确定使用什么构造函数以及确定构造函数的参数等。利用这些已经基本可以实现一个对象的实例化,当然实际上需要的东西可能更多更复杂,这里只是举个例子。那么需要的这些信息可以去哪里提取呢?对Spring有了解的可能都马上能想到BeanDefinition
,这是一份原料表,里面有我们构造一个实例化对象所需的所有参数。如果不太理解这个定义,可以参考一下上篇文章的例子。
如果不清楚BeanDefinition是从哪里来的以及不清楚如何定义的,可以参考之前的文章Spring Ioc源码分析系列--Ioc源码入口分析的关键实现系列方法 loadBeanDefinitions ()
。这篇文章讲解注册的时候只是说了注册到容器里,并没有说明具体是注册到了哪里,这里点明一下,所谓讲BeanDefinition
注册到容器里,就是将BeanDefinition
放入到容器的一个Map里,具体是注册到了DefaultListableBeanFactory
的beanDefinitionMap
属性里,beanName
会保存到beanDefinitionNames
属性里,这是个list
集合,里面的beanName
会保持注册时候的顺序。
实例化的开始就是从遍历所有的beanName
开始,话不多说,开始分析吧。
还记得实例化入口的方法名吗?回忆一下,算了,反正也不会有人记得。是beanFactory.preInstantiateSingletons()
,具体实现是在DefaultListableBeanFactory
类里。
跟进代码查看,可以看到,这段代码分为两部分,第一个for循环用于先实例化对象,第二个for循环完成一些实例化之后的回调操作。我们先来看第一个for循环,首先是遍历所有的beanNames
获取BeanDefinition
,然后根据工厂bean
和非工厂bean
进行相应处理,最后调用getBean(beanName)
实例化对象。注意这里实例化的是非抽象的、单例的并且是非懒加载的bean,这个前提非常重要。
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("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.
// 所有bd的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 遍历所有bd,一个个进行创建
for (String beanName : beanNames) {
// 获取到指定名称对应的bd
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 对不是延迟加载的单例的Bean进行创建
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是一个FactoryBean
if (isFactoryBean(beanName)) {
// 如果是一个factoryBean的话,先创建这个factoryBean,创建factoryBean时,需要在beanName前面拼接一个&符号
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
// 判断是否是一个SmartFactoryBean,并且不是懒加载的,就意味着,在创建了这个factoryBean之后要立马调用它的getObject方法创建另外一个Bean
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 不是factoryBean的话,我们直接创建就行了
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 在创建了所有的Bean之后,遍历为所有适用的 bean 触发初始化后回调,也就是这里会对延迟初始化的bean进行加载...
for (String beanName : beanNames) {
// 这一步其实是从缓存中获取对应的创建的Bean,这里获取到的必定是单例的
Object singletonInstance = getSingleton(beanName);
// 判断是否是一个SmartInitializingSingleton,
// 最典型的就是我们之前分析过的EventListenerMethodProcessor,
// 在这一步完成了对已经创建好的Bean的解析,会判断其方法上是否有 @EventListener注解,
// 会将这个注解标注的方法通过EventListenerFactory转换成一个事件监听器并添加到监听器的集合中
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
获取BeanDefinition
首先跟进getMergedLocalBeanDefinition(beanName)
方法,这里首先会尝试从mergedBeanDefinitions
里去获取,这个mergedBeanDefinitions
存放着已经合并过的BeanDefinition
,获取不到再真正调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))
去获取。
/**
* Return a merged RootBeanDefinition, traversing the parent bean definition
* if the specified bean corresponds to a child bean definition.
*
* 返回一个合并的 RootBeanDefinition,如果指定的 bean 对应于子 bean 定义,则遍历父 bean 定义。
*
* @param beanName the name of the bean to retrieve the merged definition for
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 首先检查 mergedBeanDefinitions ,最小程度影响并发性能
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
先看getBeanDefinition(beanName)
,这个方法就是简单的去beanDefinitionMap
里获取BeanDefinition
,如果获取不到,就抛出异常。beanDefinitionMap
就是上面说到的BeanDefinition
存放的地方。
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
接下来就进入到getMergedBeanDefinition()
方法获取BeanDefinition
,为啥要从beanDefinitionMap
获取了还进行一个merged获取呢?这是因为Bean有层次关系,子类需要合并父类的属性方法等,所以要进行一次合并,合并完成后会放入到mergedBeanDefinitions
里,功能和属性名区分度还是十分贴切的