上一篇我们说到了spring1.0的基本配置使用,特别需要注意的是spring1.0的bean.xml文件是没有名称空间的,只有文档的定义信息。
那么本篇,我们来看一下spring1.0版本的容器是如何初始化的,bean是怎么创建出来的,篇幅较长,请大家耐心阅读,如果有什么错误的地方,欢迎大家指正。
无论是spring1.0还是spring5.0,其核心思想都离不开容器的初始化,bean的注入,后置处理器的使用等等功能,那么spring后面的版本提供了很多复杂的功能,这对我们阅读源码有一定的影响,而spring1.0所提供的功能比较简单,阅读起来也比较方便。
好了,话不多说,我们先来看看上一篇里面,创建容器的的方法
public class MySpringTest01 {
private ClassPathXmlApplicationContext applicationContext;
@Before
public void getContext(){
//容器初始化
applicationContext = new ClassPathXmlApplicationContext("bean01.xml");
}
@Test
public void test1(){
Person person1 = (Person) applicationContext.getBean("person");
System.out.println("person1:" + person1);
Person person2 = (Person) applicationContext.getBean("person");
System.out.println("person2:" + person2);
System.out.println(person1 == person2);
}
}
下面我们来看一下ClassPathXmlApplicationContext这个类里面干了什么事情
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private String[] configLocations;
//这个就是我们上一步创建对象时调用的方法,传入了一个bean.xml地址的参数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
//将bean.xml文件地址保存在configLocations里面
this.configLocations = new String[]{configLocation};
//调用刷新容器方法
this.refresh();
}
public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
this.configLocations = configLocations;
this.refresh();
}
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
super(parent);
this.configLocations = configLocations;
this.refresh();
}
protected String[] getConfigLocations() {
return this.configLocations;
}
}
我们先看下ClassPathXmlApplicationContext这个类的继承关系
可以看到ClassPathXmlApplicationContext是继承自AbstractXmlApplicationContext的,而AbstractXmlApplicationContext又继承自AbstractApplicationContext
我们看下每个父类中的方法
从图中我们可以看到ClassPathXmlApplicationContext调用的refresh()方法,其实就是调用父类AbstractApplicationContext的refresh()方法,那我们现在主要就是分析这个方法的执行过程
public void refresh() throws BeansException {
//获取当前时间
this.startupTime = System.currentTimeMillis();
//创建beanFactory容器,同时解析bean.xml文件,并将bean的定义信息保存起来
this.refreshBeanFactory();
//获取当前容器
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
//设置类的属性编辑器
beanFactory.registerCustomEditor(class$org$springframework$core$io$Resource == null ? (class$org$springframework$core$io$Resource = class$("org.springframework.core.io.Resource")) : class$org$springframework$core$io$Resource, new ContextResourceEditor(this));
//添加自带的beanPostProcessor处理器(当前只加了ApplicationContextAwareProcessor)
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置需要忽略的接口类型
beanFactory.ignoreDependencyType(class$org$springframework$core$io$ResourceLoader == null ? (class$org$springframework$core$io$ResourceLoader = class$("org.springframework.core.io.ResourceLoader")) : class$org$springframework$core$io$ResourceLoader);
//设置需要忽略的接口类型
beanFactory.ignoreDependencyType(class$org$springframework$context$ApplicationContext == null ? (class$org$springframework$context$ApplicationContext = class$("org.springframework.context.ApplicationContext")) : class$org$springframework$context$ApplicationContext);
//空方法,留给第三方添加组件的入口
this.postProcessBeanFactory(beanFactory);
//遍历执行容器自带的beanFactoryPostProcessor
Iterator it = this.getBeanFactoryPostProcessors().iterator();
while(it.hasNext()) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor)it.next();
factoryProcessor.postProcessBeanFactory(beanFactory);
}
//判断容器中所有bean定义信息总数是否为0
if (this.getBeanDefinitionCount() == 0) {
this.logger.warn("No beans defined in ApplicationContext [" + this.getDisplayName() + "]");
} else {
this.logger.info(this.getBeanDefinitionCount() + " beans defined in ApplicationContext [" + this.getDisplayName() + "]");
}
//遍历执行所有的beanFactoryPostProcessor
this.invokeBeanFactoryPostProcessors();
//添加beanPostProcessor后置处理器
this.registerBeanPostProcessors();
//获取国际化的bean
this.initMessageSource();
//空方法,后续可能会用到初始化特别的bean
this.onRefresh();
//往事件派发器中添加的事件
this.refreshListeners();
//实例化所有还未创建的单实例bean
beanFactory.preInstantiateSingletons();
//发布事件(当前主要发布容器启动完成事件)
this.publishEvent(new ContextRefreshedEvent(this));
}
可以看到,在refresh()方法中做了很多初始化的事情,那么我们今天主要讲的是bean的实例化,所以主要看this.refreshBeanFactory();和beanFactory.preInstantiateSingletons();这个方法,其他的方法,在我们后续使用的过程中,如果用到了,我们再来讲。
this.refreshBeanFactory()这个方法呢,主要就是给我们创建一个BeanFactory的默认实例,我们点进去(Ctrl+Alt+B)看下这个方法干了什么
在点进去的过程中呢,我们发现编辑器提示我们有两个类重写了这个方法,那我们到底应该去看哪一个呢?
那么在java中,子类实例化的时候呢,会优先执行父类的实例化,我们上面说了这个继承关系(ClassPathXmlApplicationContext是继承自AbstractXmlApplicationContext的,而AbstractXmlApplicationContext又继承自AbstractApplicationContext),那么在父类执行子类的方法时,那应该是谁实例化我,我就执行谁的重写方法。所以我们这个应该看AbstractXmlApplicationContext这个类中的refreshBeanFactory()方法,这一点在我们后面的源码分析中显得尤为重要,spring中用到了很多的继承和接口,所以我们看源码的过程中一定要把类继承树搞清楚。
protected void refreshBeanFactory() throws BeansException {
try {
//调用创建bean的方法
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
this.beanFactory = beanFactory;
if (this.logger.isInfoEnabled()) {
this.logger.info("Bean factory for application context '" + this.getDisplayName() + "': " + beanFactory);
}
} catch (IOException var3) {
throw new ApplicationContextException("I/O error parsing XML document for application context [" + this.getDisplayName() + "]", var3);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
//直接newDefaultListableBeanFactory返回
return new DefaultListableBeanFactory(this.getParent());
}
在上面的方法中,我们可以看到最后的beanFactory就是new了一个DefaultListableBeanFactory对象,这个方法里面还涉及到将xml文件解析成beanDefinition,并将beanDefinition保存在DefaultListableBeanFactory的beanDefinitionNames和beanDefinitionMap两个属性中的工作,这个暂时不去拓展,感兴趣的可以自己研究。
接下来看下beanFactory.preInstantiateSingletons()这个方法,这个方法在DefaultListableBeanFactory类中
public void preInstantiateSingletons() {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in factory [" + this + "]");
}
//遍历beanDefinitionNames集合
Iterator it = this.beanDefinitionNames.iterator();
while(it.hasNext()) {
String beanName = (String)it.next();
//判断beanDefinitionMap是不是包含这个bean的名称
if (this.containsBeanDefinition(beanName)) {
//获取bean的定义信息BeanDefinition
RootBeanDefinition bd = this.getMergedBeanDefinition(beanName, false);
//判断bean是否为单例并且不是懒加载
if (bd.isSingleton() && !bd.isLazyInit()) {
//判断bean是不是FactoryBean类型的
if ((class$org$springframework$beans$factory$FactoryBean == null ? (class$org$springframework$beans$factory$FactoryBean = class$("org.springframework.beans.factory.FactoryBean")) : class$org$springframework$beans$factory$FactoryBean).isAssignableFrom(bd.getBeanClass())) {
FactoryBean factory = (FactoryBean)this.getBean("&" + beanName);
if (factory.isSingleton()) {
this.getBean(beanName);
}
} else {
//获取bean
this.getBean(beanName);
}
}
}
}
}
根据配置及断点调试,我们的bean是在beanDefinitionMap中的,并且是单例,不是懒加载,也不是通过实现FactoryBean来创建,所以执行到这段代码的最后一步this.getBean(beanName),那么我们看看this.getBean(beanName)又做了哪些事?这个方法在AbstractBeanFactory中
public Object getBean(String name) throws BeansException {
//处理bean的名称,判断名称中是否包含"&",如果包含,则去掉,判断bean的名称是否用的别名,如果是,则返回别名对应的实际beanName
String beanName = this.transformedBeanName(name);
//从单实例bean缓存中获取bean对象
Object sharedInstance = this.singletonCache.get(beanName);
//如果对象不为空,则返回这个对象
if (sharedInstance != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
//去判断这个对象是否需要由FactoryBean来创建,如果不是,则直接返回该对象
return this.getObjectForSharedInstance(name, sharedInstance);
} else {//如果缓存中没有这个对象
RootBeanDefinition mergedBeanDefinition = null;
try {
//获取该bean的定义信息
mergedBeanDefinition = this.getMergedBeanDefinition(beanName, false);
} catch (NoSuchBeanDefinitionException var7) {
if (this.parentBeanFactory != null) {
return this.parentBeanFactory.getBean(name);
}
throw var7;
}
//判断bean是否是单例
if (mergedBeanDefinition.isSingleton()) {
synchronized(this.singletonCache) {
//如果是单例,则从缓存中获取一次
sharedInstance = this.singletonCache.get(beanName);
//如果缓存中没有
if (sharedInstance == null) {
this.logger.info("Creating shared instance of singleton bean '" + beanName + "'");
//创建bean对象
sharedInstance = this.createBean(beanName, mergedBeanDefinition);
//添加到缓存中
this.addSingleton(beanName, sharedInstance);
}
}
//再执行一次返回bean的逻辑(去判断这个对象是否需要由FactoryBean来创建,如果不是,则直接返回该对象)
return this.getObjectForSharedInstance(name, sharedInstance);
} else {
//如果不是单实例,则直接调用创建bean的方法,但是不会去缓存这个bean
return this.createBean(name, mergedBeanDefinition);
}
}
}
由于这里我们是创建一个普通的bean,没有通过实现FactoryBean方式来创建bean,所以暂时不考虑这种方法,等到后面我们用到的时候,再去分析。我们先暂且看普通bean的创建方式,根据注释,我们知道一般的bean是调用this.createBean(beanName, mergedBeanDefinition)来创建bean,那我们来断点调试一下具体是怎么创建的。
this.createBean(beanName, mergedBeanDefinition)的具体实现是在AbstractAutowireCapableBeanFactory中的,为什么会在这个类中,就像上面我们提到的,还是得看继承关系:
可以看到AbstractBeanFactory调用createBean其实就是调用子类AbstractAutowireCapableBeanFactory的createBean
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mergedBeanDefinition + "]");
}
//判断该bean是否有依赖,如果有依赖,则先创建依赖bean,又走一遍上一步的getBean方法
if (mergedBeanDefinition.getDependsOn() != null) {
for(int i = 0; i < mergedBeanDefinition.getDependsOn().length; ++i) {
this.getBean(mergedBeanDefinition.getDependsOn()[i]);
}
}
//创建一个bean的包装对象(将bean封装到这个对象中,这样对spring内部提供了统一的bean访问方式,包括bean的实例,bean的属性等等)
BeanWrapper instanceWrapper = null;
//判断这个bean创建时,是否调用了有参构造器
if (mergedBeanDefinition.getResolvedAutowireMode() != 3 && !mergedBeanDefinition.hasConstructorArgumentValues()) {//如果没有有参构造器
//直接创建bean并包装成BeanWrapper
instanceWrapper = new BeanWrapperImpl(mergedBeanDefinition.getBeanClass());
//解析这个实例的属性,并封装到BeanWrapper
this.initBeanWrapper((BeanWrapper)instanceWrapper);
} else {
instanceWrapper = this.autowireConstructor(beanName, mergedBeanDefinition);
}
//通过BeanWrapper获取到当前这个对象的bean实例
Object bean = ((BeanWrapper)instanceWrapper).getWrappedInstance();
//如果这个bean是单例,则添加到单例容器中
if (mergedBeanDefinition.isSingleton()) {
this.addSingleton(beanName, bean);
}
//为这个实例进行赋值操作
this.populateBean(beanName, mergedBeanDefinition, (BeanWrapper)instanceWrapper);
try {
//判断当前bean是否实现了BeanNameAware接口,如果有,则执行这个接口的实现方法
if (bean instanceof BeanNameAware) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invoking setBeanName() on BeanNameAware bean '" + beanName + "'");
}
((BeanNameAware)bean).setBeanName(beanName);
}
//判断这个bean是否实现了BeanFactoryAware接口,如果有,则执行这个接口的实现方法
if (bean instanceof BeanFactoryAware) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invoking setBeanFactory() on BeanFactoryAware bean '" + beanName + "'");
}
((BeanFactoryAware)bean).setBeanFactory(this);
}
//执行这个bean的后置处理器的初始化方法执行之前的方法
bean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
//执行这个bean的初始化方法(注意,不是实例化方法,初始化方法是可以在xml设定的,默认没有)
this.invokeInitMethods(bean, beanName, mergedBeanDefinition);
//执行这个bean的后置处理器的初始化方法执行之后的方法
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
//返回这个bean
return bean;
} catch (InvocationTargetException var6) {
throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName, "Initialization of bean failed", var6.getTargetException());
} catch (Exception var7) {
throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName, "Initialization of bean failed", var7);
}
}
至此,我们这个bean就已经创建完成了,并可以在容器中使用了。下一节,我们将介绍FactoryBean创建bean的方式。