我们现在经常使用的beanFactory有两种,一种是xml方式的, 另一种是注解方式的. 其实使用注解的更多一些. xml和注解方式的bean工厂在初始化的时候也是有区别的.
从上图可以看出, 获取两种方式的bean工厂的区别
- AbstractRefreshableApplicationContext: 基于xml配置文件的方式
- GenericApplicationContext: 基于注解的方式. 基于注解实现的里面代码很简单, 只是刷新的beanFactory. 没有耦合加载beanDefinition的流程. 基于xml实现的代码, 里面耦合了加载beanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
/**
* 刷新bean工厂,判断bean工厂是否已经存在,如果存在需要进行销毁和关闭
* 默认调用的是AbstractRefreshableApplicationContext的refreshBeanFactory方法.
* 刷新Bean工厂时会进行bean定义的加载操作。
*/
refreshBeanFactory();
return getBeanFactory();
}
刷新bean工厂,判断bean工厂是否已经存在,如果存在需要进行销毁和关闭,我们接着继续往下看。先来看看基于注解方式的, 基于注解方式只是指定了bean工厂的序列化ID
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
// 指定bean工厂的序列化ID
this.beanFactory.setSerializationId(getId());
}
再来看看基于xml方式的, 基于xml方式的 除了指定了bean工厂的序列化id, 还耦合加载了beanDefinition
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断bean工厂是否存在,如果存在需要先销毁和关闭。否则会出现问题
if (hasBeanFactory()) {
// 销毁bean,根据bean的名称将bean工厂中的所有bean都从map中移除
destroyBeans();
// 关闭bean工厂,设置Bean工厂的序列化id为null,并将beanFactory的值赋值为null
closeBeanFactory();
}
try {
// 重新创建bean工厂,默认返回的是Bean工厂类型是:DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化ID,ID: class名称 + "@" + 对象的十六进制值
beanFactory.setSerializationId(getId());
// 定制bean工厂。作用:设置bean定义是否可以被覆盖以及设置bean在创建的时候是否允许循环引用.
customizeBeanFactory(beanFactory);
// 解析并加载bean的定义,默认是通过AbstractXmlApplicationContext类中的loadBeanDefinitions实现
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
refreshBeanFactory一共做了几件事情;
- 判断bean工厂是否存在,如果存在需要先销毁和关闭。否则会出现问题;
- 重新创建bean工厂,默认返回的是Bean工厂类型是:DefaultListableBeanFactory;
- 设置序列化ID,ID: class名称 + “@” + 对象的十六进制值;
- 定制bean工厂。作用:设置bean定义是否可以被覆盖以及设置bean在创建的时候是否允许循环引用.
解析并加载bean的定义,默认是通过AbstractXmlApplicationContext类中的loadBeanDefinitions实现;
<br /> 我们接下来看它是如果创建DefaultListableBeanFactory的。
```java // AbstractRefreshableApplicationContext
protected DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// DefaultListableBeanFactory public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
// AbstractAutowireCapableBeanFactory
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}
/**
* Create a new AbstractAutowireCapableBeanFactory.
* ignoreDependencyInterface:方法用来在自动装配时自动忽略类或者接口子类的注入.
*/
public AbstractAutowireCapableBeanFactory() {
super();
// 在Bean自动装配时自动忽略BeanNameAware子类的注入
ignoreDependencyInterface(BeanNameAware.class);
// 忽略BeanFactoryAware接口子类的注入
ignoreDependencyInterface(BeanFactoryAware.class);
// 忽略BeanClassLoaderAware接口子类的注入
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
接下来看下customizeBeanFactory是如何定制BeanFactory的。
```java
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
// 是否允许覆盖Bean的定义
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 该属性在解决Spring Bean的循环依赖中会使用到
// 如果该属性的值为true,而且将要初始化的bean为单例,而且正在创建中,则在初始化属性前会把该bean的信息放入到singletonFactories中.
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
两个属性,allowBeanDefinitionOverriding是否允许覆盖Bean的定义,allowCircularReferences该属性在解决Spring Bean的循环依赖中会使用到。
接下来我们来看下loadBeanDefinitions,这里loadBeanDefinitions是一个重载方法大家看的时候不要被绕晕了。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建Xml格式的Bean读取器,里面会设置bean工厂的资源加载器及环境信息
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 对象创建bean读取器的时候已经初始化.此处直接获取
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 上述创建时已经初始化,此处直接获取
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
// 会解析xml中的标签属性,并添加到bean定义中.
loadBeanDefinitions(beanDefinitionReader);
}
他首先是创建Xml格式的Bean读取器,里面会设置bean工厂的资源加载器及环境信息,然后对beanDefinitionReader进行一些属性赋值,最后就会解析xml中的标签属性,并添加到bean定义中,我们具体看对应的解析源码;
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 通过另外一个构造函数构造的容器,会使用configResources的方式去加载bean定义
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 获取所有的配置文件名称,例如:{"beans.xml"}。主要是xml配置文件的名称
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}