上一节中将了如何通过xml文件中读取到bean的定义,链接为 Spring 二、主要逻辑代码赏析之获取bean的定义 ,这一节中,我们将会讲述读取出xml文件后,如何根据bean的定义来最终生成bean。
首先还是来看一下
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
初始的时候的refresh() 方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
. . .
// 此为获取一个 DefaultListableBeanFactory 的 beanFactory,并且会生成 XmlBeanDefinitionReader ,从xml文件中读出beanDefinition并放置到 beanFactory中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
. . .
// DefaultListableBeanFactory 会在此方法中根据 BeanDefinition 去加载bean的定义。
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
. . .
// Propagate exception to caller.
throw ex;
}
finally {
. . .
}
}
}
可以看到 ,是在 finishBeanFactoryInitialization(beanFactory) 方法中将beanDefinition生成bean的。
下面我们看一下 DefultListableBeanFactory来获取bean的方法:
@Override
public void preInstantiateSingletons() throws BeansException {
// 得到所有的bean定义的name列表
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 遍历bean定义name的列表,得到对应的bean定义
for (String beanName : beanNames) {
this.logger.debug("beanName 为" + beanName);
// 得到bean的定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是工厂类的bean
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);
}
}
//