懒加载和非懒加载
懒加载指的是spring容器初始化的时候并不实例,当用到的时候才实例化,需要在标签上指定”lazy-init”属性值为true,用到的时候不只是直接使用,或者是被别的非懒加载bean依赖了。
非赖加载指的是spring容器初始化的时候实例化bean,bean不限制是单例(singleton)还是多例(prototype)但是都只实例一个bean,一般bean都是非懒加载,除非bean比较耗资源。
既然了解到什么是非懒加载的bean就知道这类bean是在初始化spring容器的时候初始化的,那么延续上篇文章继续读源码。
refresh()之finishBeanFactoryInitialization()
AbstractApplicationContext的refresh()里面的this.finishBeanFactoryInitialization(beanFactory)
,我们来读读
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
String[] var3 = weaverAwareNames;
int var4 = weaverAwareNames.length;
for(int var5 = 0; var5 < var4; ++var5) {
String weaverAwareName = var3[var5];
this.getBean(weaverAwareName);
}
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
}
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
先判断beanFactory里面是否有类型转换服务bean有就设置转换服务;然后给beanFactory设置一个null临时类加载器-停止使用用于类型匹配的临时类加载器;然后把非懒bean的名字赋值给frozenBeanDefinitionNames,冻结所有的bean定义,表明已注册的bean定义将不会被修改或后处理。
下面一个方法是真正的主角beanFactory.preInstantiateSingletons();
,实例全部剩余非懒加载单例bean
finishBeanFactoryInitialization()之preInstantiateSingletons()
class DefaaultListableBeanFactory...
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("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<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
迭代一个beanNames副本为了给init方法用,该方法依次注册新的bean定义。beanNames有值就根据beanName获得RootBeanDefinition,这个Rootbean定义表示合并的bean定义,在spring beanFactory运行时返回一个特定的bean。它可能是由多个相互继承的原始bean定义创建的。一个RootBean本质上是统一的bean定义视图;如果是抽象的、不是单例的、是懒加载的就继续判断是否是工厂bean,不是的话就进入this.getBean(beanName);
,由于还没初始化所以工厂bean里面根本就存在所以直接执行this.getBean(beanName);
。
preInstantiateSingletons()之this.getBean(beanName)
这个getBean最终调用的是AbstractBeanFactory的doGetBean(),代码很长,我们慢慢读。
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if(sharedInstance != null && args == null) {
if(this.logger.isDebugEnabled()) {
if(this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug(