Spring容器启动,扫描得到所有BeanDefinition之后,就会先实例化所有非懒加载的单例Bean的
入口
Spring容器启动刷新的方法里:
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
我们知道beanFacotory就是DefaultListableBeanFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
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.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {//1. 合并BeanDefinitionRootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//判断BeanDefinition,非抽象,是单例,非懒加载if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//2. FactoryBean逻辑,第二节提到过if (isFactoryBean(beanName)) {//FACTORY_BEAN_PREFIX="&"Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {...}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {//创建真正的Bean对象(这里是FactoryBean.getObject()对象)getBean(beanName);}}}else {//3. 创建Bean对象getBean(beanName);}}}// 4. 所有非懒加载单例Bean都创建完成后// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {// 从单例池里拿beanName对应的单例Bean(里面实现涉及到循环依赖,以后讲,先简单理解)Object singletonInstance = getSingleton(beanName);// 判断单例Bean是否实现了SmartInitializingSingleton接口// 这个接口也属于Spring生命周期里的一种接口if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {...}else {//触发afterSingletonsInstantiated方法smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}
}
1. 合并BeanDefinition
应用场景
通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在Spring中支持父子BeanDefinition,和Java父子类类似,但是完全不是一回事。
BeanDefinition也可以设置成抽象的,这样该BeanDefinition就不会创建Bean实例,可以被其他BeanDefinition继承(不设置抽象也能继承)
父子BeanDefinition实际用的比较少,使用是这样的,比如:
这么定义的情况下,child是单例Bean:
<bean id="parent" class="com.yth.service.Parent" scope="prototype"/>
<bean id="child" class="com.yth.service.Child"/>
但是这么定义的情况下,child就是原型Bean了:
<bean id="parent" class="com.yth.service.Parent" scope="prototype"/>
<bean id="child" class="com.yth.service.Child" parent="parent"/>
因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。
源码分析
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// Quick check on the concurrent map first, with minimal locking.// 合并过,就直接返回RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);if (mbd != null && !mbd.stale) {return mbd;}return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)throws BeanDefinitionStoreException {return getMergedBeanDefinition(beanName, bd, null);
}
mergedBeanDefinitions:合并之后的BeanDefinition Map,value就是RootBeanDefinition
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)throws BeanDefinitionStoreException {synchronized (this.mergedBeanDefinitions) {RootBeanDefinition mbd = null;RootBeanDefinition previous = null;// Check with full lock now in order to enforce the same merged instance.if (containingBd == null) {...}if (mbd == null || mbd.stale) {previous = mbd;// 判断有没有父亲if (bd.getParentName() == null) {// Use copy of given root bean definition.// 没有parent就生成一个新的RootBeanDefinitionif (bd instanceof RootBeanDefinition) {//复制新的mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else {//new新的mbd = new RootBeanDefinition(bd);}}else {// Child bean definition: needs to be merged with parent.BeanDefinition pbd;try {// 获取parentName对应的BeanDefinitionString parentBeanName = transformedBeanName(bd.getParentName());if (!beanName.equals(parentBeanName)) {//递归获取父亲的RootBeanDefinitionpbd = getMergedBeanDefinition(parentBeanName);}//如果beanName和parentName一样,则从父亲工厂里获取BeanDefinitionelse {...}}//最终获取不到会抛异常catch (NoSuchBeanDefinitionException ex) {...}// Deep copy with overridden values.// 深拷贝,生成一个RootBeanDefinition// 先基于父BeanDefinition生成RootBeanDefinitionmbd = new RootBeanDefinition(pbd);// 然后和自己合并,自己优先级更高mbd.overrideFrom(bd);}// Set default singleton scope, if not configured before.if (!StringUtils.hasLength(mbd.getScope())) {...}// A bean contained in a non-singleton bean cannot be a singleton itself.// Let's correct this on the fly here, since this might be the result of// parent-child merging for the outer bean, in which case the original inner bean// definition will not have inherited the merged outer bean's singleton status.if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {...}// Cache the merged bean definition for the time being// (it might still get re-merged later on in order to pick up metadata changes)if (containingBd == null && isCacheBeanMetadata()) {//保存到mergedBeanDefinitions Mapthis.mergedBeanDefinitions.put(beanName, mbd);}}if (previous != null) {...}return mbd;}
}
真正创建Bean的时候,用的是合并之后的这个Map:mergedBeanDefinitions
2. FactoryBean
2.1 判断是否是FactoryBean
org.springframework.beans.factory.support.AbstractBeanFactory#isFactoryBean(java.lang.String)
这个方法除了这,其他地方也会掉
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {String beanName = transformedBeanName(name);//先从单例池获取FactoryBean本身的对象Object beanInstance = getSingleton(beanName, false);if (beanInstance != null) {return (beanInstance instanceof FactoryBean);}//没有拿到FactoryBean本身的对象,则根据BeanDefinition对象来判断// 当前容器没有name对应的BeanDefinition,则从父容器获取// No singleton instance found -> check bean definition.if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {// No bean definition found in this factory -> delegate to parent.return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);}//拿到合并后的BeanDefinition判断是否是FactoryBeanreturn isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {//根据BeanDefinition的isFactoryBean属性判断Boolean result = mbd.isFactoryBean;if (result == null) {//isFactoryBean属性缓存为空,则直接根据类的类型判断//根据BeanDefinition推测Bean类型(获取BeanDefinition的beanClass属性)Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);//判断是否实现了FactoryBean接口result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));mbd.isFactoryBean = result;}return result;
}
BeanDefinition里的很多属性,其实是起到缓存的作用,一开始为null也不影响,会去专门解析,然后在保存起来作为缓存使用。
2.2 创建FactoryBean本身的对象
getBean源码见2.4(带一点)、或者3(下一章节讲解)。
2.3 SmartFactoryBean
如果我们FactoryBean实现的是SmartFactoryBean接口:
并重写了isEagerInit方法,返回true:
那么Spring容器启动的时候,就会把改FactoryBean对应的getObject()方法的对象生成,否则只有getBean的时候才会生成。
没有调getBean已经有了:
2.4 FactoryBean的getObject触发时机
FactoryBean对应的getObject对象是通过调容器getBean方法实例化的
- beanName获取FactoryBean的getObject对象
- “&” + beanName获取FactoryBean本身的对象
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {//name有可能是 &xxx 或者 xxx//如果name是&xxx,beanName返回的beanName就是xxx//name如果是别名,beanName就是idString beanName = transformedBeanName(name);Object beanInstance;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {...}//如果sharedInstance是FactoryBean,那么就调用getObject()返回对象beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {...}return adaptBeanInstance(name, beanInstance, requiredType);
}
//name是&xxx或者xxx
//beanName是xxx
//beanInstance从单例池里拿到的bean
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.// 判断name是不是带了&符号,是的话就是FactoryBean的引用if (BeanFactoryUtils.isFactoryDereference(name)) {//走到这说明想获取FactoryBean本身if (beanInstance instanceof NullBean) {return beanInstance;}//判断从单例池里拿到的Bean是不是FactoryBeanif (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}if (mbd != null) {mbd.isFactoryBean = true;}//是,则直接返回return beanInstance;}//走到这说明想获取的是普通Bean对象,或者FacotryBean的getObject对象// 单例池里的对象不是FactoryBean,则直接返回if (!(beanInstance instanceof FactoryBean)) {//返回普通对象return beanInstance;}Object object = null;if (mbd != null) {mbd.isFactoryBean = true;}else {//先从缓存拿object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());//核心在这里object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;
}
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {if (factory.isSingleton() && containsSingleton(beanName)) {//多线程同时来创建需要控制,保证单例synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {//核心在这object = doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls)Object alreadyThere = this.factoryBeanObjectCache.get(beanName);if (alreadyThere != null) {...}else {//是否要进行后处理,可以发现FactoryBean只会经过“初始化后”的生命周期if (shouldPostProcess) {...}if (containsSingleton(beanName)) {//放到缓存this.factoryBeanObjectCache.put(beanName, object);}}}return object;}}//FactoryBean也支持多例情况else {...}
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {Object object;try {if (System.getSecurityManager() != null) {...}else {//这里调用了FactoryBean的getObject方法object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {...}catch (Throwable ex) {...}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null) {if (isSingletonCurrentlyInCreation(beanName)) {...}object = new NullBean();}return object;
}
3. 创建Bean对象
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
下一章节讲。
4. SmartInitializingSingleton
应用场景
定义一个单例Bean的时候,可以实现SmartInitializingSingleton接口,它会在所有非懒加载的单例Bean都创建成功以后触发。注意!!是在所有!
源码分析
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons