深入理解Spring系列之六:bean初始化
《深入理解Spring系列之四:BeanDefinition裝載前奏曲》中提到,對於非延遲單例bean的初始化在finishBeanFactoryInitialization(beanFactory)中完成。進入這個方法,程式碼如下。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
關注最後一行程式碼,
beanFactory.preInstantiateSingletons()完成初始化所有非延遲的單例bean,進入這個方法的具體實現,程式碼如下。
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 beanNames = new ArrayList(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singletonbeans...
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() {
@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() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
從上面的程式碼中看到,只會對非延遲單例bean進行初始化,scope為其它值的bean會在使用到的時候進行初始化,如prototype。這裡關注getBean方法,這個方法看著很眼熟,其實就是《深入理解Spring系列之一:開篇》示例程式碼中用到的getBean,Spring對這個方法做了重複使用。getBean方法的具體實現在doGetBean方法中,這個方法的程式碼很長就不貼程式碼了。在doGetBean中,首先會初始化其依賴的bean,然後進行自身的初始化,這個方法裡關注如下的程式碼段。
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that receiveda temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
這段程式碼完成了單例bean的初始化,追蹤程式碼進入doCreateBean方法中,在這個方法中進行bean例項的建立、屬性填充、將bean例項加入單例bean例項的快取中。doCreateBean方法中有如下程式碼段。
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
createBeanInstance方法裡完成bean例項的建立,具體過程可繼續追蹤程式碼檢視,其實就是使用反射進行例項物件的建立。
相關文章
- 【spring原始碼系列】之【Bean的初始化】Spring原始碼Bean
- Spring容器 —— 深入 bean 的載入(五、初始化 bean)SpringBean
- 深入理解Spring系列之十三:IntrospectorCleanupListener解析SpringROS
- 4、深入理解BeanBean
- Spring核心系列之Bean的注入SpringBean
- Spring中Bean及@Bean的理解SpringBean
- 《Spring》(六)---- Bean的scopeSpringBean
- 深入理解MySQL系列之鎖MySql
- 深入理解MySQL系列之索引MySql索引
- Spring IoC bean 的初始化SpringBean
- Spring Bean如何初始化的SpringBean
- spring原始碼深度解析— IOC 之 bean 的初始化Spring原始碼Bean
- Spring裝配Bean(六)Bean的作用域SpringBean
- 【spring原始碼系列】之【Bean的銷燬】Spring原始碼Bean
- 深入Weex系列(六)之Weex渲染流程分析
- spring原始碼之bean的初始化及迴圈引用Spring原始碼Bean
- Spring系列第六講 玩轉bean scope,避免跳坑裡!SpringBean
- Spring系列第十二講 lazy-init:bean延遲初始化SpringBean
- 【spring原始碼系列】之【Bean的生命週期】Spring原始碼Bean
- Spring框架系列(二)之Bean的註解管理Spring框架Bean
- Spring核心系列之Bean的生命週期SpringBean
- Spring系列.Bean簡介SpringBean
- 深入理解javascript系列(六):作用域與作用域鏈JavaScript
- 深入理解Spring的Bean定義物件BeanDefinition-面試重點SpringBean物件面試
- Spring 原始碼(17)Spring Bean的建立過程(8)Bean的初始化Spring原始碼Bean
- 【spring原始碼系列】之【Bean的屬性賦值】Spring原始碼Bean賦值
- 【spring原始碼系列】之【Bean的迴圈依賴】Spring原始碼Bean
- Spring Security系列之認證過程(六)Spring
- spring使用註解注入bean理解SpringBean
- spring4.1.8擴充套件實戰之六:註冊bean(BeanDefinitionRegistryPostProcessor)Spring套件Bean
- Spring原始碼解析之八finishBeanFactoryInitialization方法即初始化單例beanSpring原始碼Bean單例
- Spring入門(六):條件化的beanSpringBean
- 深入理解Go系列一之指標變數Go指標變數
- SpringIOC二—— 容器 和 Bean的深入理解SpringBean
- 深入剖析Redis系列(六) - Redis資料結構之雜湊Redis資料結構
- 深入理解javascript系列(十一):thisJavaScript
- 【前端Talkking】CSS系列——CSS深入理解之absolute定位前端CSS
- redis之(二十一)redis之深入理解Spring Redis的使用RedisSpring