3、Spring之Bean生命周期~合并BeanDefinition
合并BeanDefinition
spring通过扫描,将class文件封装成BeanDefinition之后,并不能直接拿BeanDefinition去创建Bean对象,中间还需要经过一系列的合并和判断,废话不多说,直接上代码;
Bean扫描的源码请移步到另一篇博客观看《Spring之Bean生命周期~扫描》
java
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) {
// 获取合并后的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 获取FactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 创建真正的Bean对象(getObject()返回的对象)
getBean(beanName);
}
}
} else {
// 创建Bean对象
getBean(beanName);
}
}
}
System.out.println("=====调用SmartInitializingSingleton接口的afterSingletonsInstantiated方法=====");
// 所有的非懒加载单例Bean都创建完了后
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
通过preInstantiateSingletons()方法 中代码我们可以看到,spring扫描完成之后,会循环beanName集合:
- 调用getMergedLocalBeanDefinition()合并BeanDefinition,拿到最终的BeanDefinition之后就会去创建非懒加载的单例Bean;
- 首先判断BeanDefinition不是抽象的,是单例的,不是懒加载的;
- 判断Bean是否是FactoryBean;
- 判断是不是实现的SmartFactoryBean接口,如果是判断isEagerInit方法返回是true还是flash,true的话会在spring容器启动的时候去创建getObject方法返回的对象,如果不是等调用getBean时候才回去创建getObject方法返回的对象;
- 不是FactoryBean直接调用getBean方法去创建对象;
getMergedLocalBeanDefinition()
getMergedLocalBeanDefinition()方法
java
/**
* Map from bean name to merged RootBeanDefinition.
*/
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
* Return a merged RootBeanDefinition, traversing the parent bean definition
* if the specified bean corresponds to a child bean definition.
*
* @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.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
通过上述代码我们可以看到首先回去mergedBeanDefinitions缓存中判断,这个BeanDefinitions是否已经合并过,如果合并过直接拿缓存中的对象,缓存中没有的话,调用getMergedBeanDefinition()方法;
getMergedBeanDefinition()方法
getMergedBeanDefinition()方法
java
/**
* Map from bean name to merged RootBeanDefinition.
*/
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
* Return a RootBeanDefinition for the given bean, by merging with the
* parent if the given bean's definition is a child bean definition.
*
* @param beanName the name of the bean definition
* @param bd the original bean definition (Root/ChildBeanDefinition)
* @param containingBd the containing bean definition in case of inner bean,
* or {@code null} in case of a top-level bean
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
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) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
mbd = new RootBeanDefinition(bd);
}
} else {
// Child bean definition: needs to be merged with parent.
// pbd表示parentBeanDefinition
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
} else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
} else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 子BeanDefinition的属性覆盖父BeanDefinition的属性,这就是合并
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 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()) {
mbd.setScope(containingBd.getScope());
}
// 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()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
合并beanDefinition和java中的类继承一样,子类有的用子类,子类没有的用父类;合并后会得到一个RootBeanDefinition。合并完成之后,回到preInstantiateSingletons()方法;