(一)Spring IoC原始碼-3.其他特性的實現原理-01lazy-init與預例項化
阿新 • • 發佈:2018-12-30
前面的文章也提到過,IOC容器初始化過程一般不包含Bean載入的實現。Bean載入一般發生在應用第一次通過getBean向容器索取Bean的時候。但有一個例外:如果在XML檔案中為Bean定義了lazy-init屬性,那麼Bean的載入在IOC容器初始化時就預先完成了,我們將其稱為預例項化。預例項化雖然會對容器初始化的效能有一些影響,但卻能夠提高應用第一次取得Bean的效能。
在上下文的初始化過程中,也就是refresh中的程式碼實現,可以看到預例項化是整個refresh初始化IoC容器的一個步驟。在AbstractApplicationContext中看一下refresh的實現。
@Override
public void refresh() throws BeansException, IllegalStateException {
...
...
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
...
...
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
...
...
beanFactory.preInstantiateSingletons();
...
...
}
在finishBeanFactoryInitialization的方法中,封裝了對lazy-init屬性的處理,實際的處理是在DefaultListableBeanFactory這個基本容器的preInstantiateSingletons方法中完成的。
@Override
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<>(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((PrivilegedAction<Boolean>) () ->
((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((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}