我们现在经常使用的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
@Overrideprotected 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工厂的序列化IDthis.beanFactory.setSerializationId(getId());}
再来看看基于xml方式的, 基于xml方式的 除了指定了bean工厂的序列化id, 还耦合加载了beanDefinition
@Overrideprotected final void refreshBeanFactory() throws BeansException {// 判断bean工厂是否存在,如果存在需要先销毁和关闭。否则会出现问题if (hasBeanFactory()) {// 销毁bean,根据bean的名称将bean工厂中的所有bean都从map中移除destroyBeans();// 关闭bean工厂,设置Bean工厂的序列化id为null,并将beanFactory的值赋值为nullcloseBeanFactory();}try {// 重新创建bean工厂,默认返回的是Bean工厂类型是:DefaultListableBeanFactoryDefaultListableBeanFactory 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的。```javaprotected 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是一个重载方法大家看的时候不要被绕晕了。
@Overrideprotected 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);}}
