请你参考源码说一下spring的实例化以及初始化过程?

  • Post author:
  • Post category:其他


在这里插入图片描述

开始DeBUG流程:

1、创建beanFactory容器
2、加载配置文件,解析bean定义信息,包装成BeanDefinition
3、执行BeanFactoryPostProcessor

准备工作:准备BeanPostProcessor,广播器,监听器
4、实例化操作
5.初始化操作
6、获取对象


ApplicationContext.refresh()

前戏,做容器刷新前的准备工作
1、设置容器的启动时间
2、设置活跃状态为true
3、设置关闭状态为false
4、获Environment对象,并加载当前系统的属性值到Environment对象中
5、准备监听器和事件的集合对象,默认为空的集合
// Prepare this context for refreshing.
prepareRefresh();
// 创建容器对象: DefaultListableBeanFactory
// 加载xmL配置文件的属性值到当前工厂中,最重要的就是BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	@Override
	protected final void refreshBeanFactory() throws BeansException {
	//如果存在beanFactroy,则销毁beanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
		// 创建defaultListableBeanFactroy对象
			DefaultListableBeanFactory beanFactory = createBeanFactory(); 
			// 为了序列化制定Id,可以从id反序列化到beanFactroy对象
			beanFactory.setSerializationId(getId());
			// 定制beanFactory 设置相关信息, 包括是否允许覆盖同名称的不同定义的对象,以及循环依赖
			customizeBeanFactory(beanFactory);
			// 初始化documentReader,并进行XML文件读取以及解析, 自定义标签的解析
			loadBeanDefinitions(beanFactory);
			// 执行完之后:步骤2、加载配置文件,解析bean定义信息,包装成BeanDefinition
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

// beanFacotry的准备工作,对各种属性进行填充
prepareBeanFactory(beanFactory);
// allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的。
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 调用各种beanFactory后置处理器
// 步骤3、执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
// 准备工作:准备BeanPostProcessor,广播器,监听器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 支持国际化操作
initMessageSource();
// Initialize event multicaster for this context.
// 初始化上下文事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
 onRefresh();
// Check for listener beans and register them.
// 在所有注册的bean中查找Listener bean ,注册到消息广播器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非懒加载的)单例。
finishBeanFactoryInitialization(beanFactory);
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();		

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 当获取到beanName之后,会直接创建吗?先从容器中获取,如果获取不到再创建.
for (String beanName : beanNames) {
	getBean(beanName);
		doGetBean(name, null, null, false);
			createBean(beanName, mbd, args);
				createBean(beanName, mbd, args);
								instanceWrapper = createBeanInstance(beanName, mbd, args);
									{
											Class<?> beanClass = resolveBeanClass(mbd, beanName);
											constructorTouse = clazz . getDeclaredConstructor();
											ctor.newInstance ( argsWithDefaultValues ) ;
}
}	

这时,已经完成了实例化操作:

在这里插入图片描述

接下来,属性填充:但是,beanFactory applicationConext 是通过aware接口设置的,此时没有值。

populateBean(beanName, mbd, instanceWrapper);

在这里插入图片描述

invokeAwareMethods(beanName, bean);

private void invokeAwareMethods(final String beanName, final Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

此时,只有一个赋值,beanFactory:

在这里插入图片描述

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

在这里插入图片描述

执行初始化方法:

invokeInitMethods(beanName, wrappedBean, mbd);

最后执行一下:

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);



1 Bean的一生从总体上来说可以分为两个阶段:

1、容器启动阶段

2、Bean实例化阶段



1.1 容器的启动阶段都做的是预热工作:

1、配置元信息:Spring IOC容器将对象实例的创建与对象实例的使用分离,业务中需要依赖哪个对象不再依靠我们自己手动创建,Spring就会以注入的方式交给我们需要的依赖对象。Spring需要知道创建一个对象实例所需要的一些必要的信息,而这些必要的信息可以是xml配置文件,也可以是现在主流的注解,创建对象所需要的必要信息称为配置元信息。

2、BeanDefination:Spring在内存中表示这些配置元信息的方式是BeanDefination,配置元信息被加载到内存之后是以BeanDefination的形存在的。

3、BeanDefinationReader:读取xml配置元信息,那么可以使用XmlBeanDefinationReader;要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载;要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination。

4、BeanDefinationRegistry:Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。

5、BeanFactoryPostProcessor:BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如使用占位符配置元信息,例如配置Jdbc的DataSource连接的时候可以这样配置:

 <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  

BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。至此,整个容器启动阶段就算完成了,容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination了,这就是Spring为Bean实例化所做的预热的工作:

在这里插入图片描述



1.2 Bean实例化阶段

选择懒加载的方式,那么直到我们伸手向Spring要依赖对象实例之前,其都是以BeanDefinationRegistry中的一个个的BeanDefination的形式存在,也就是Spring只有在我们需要依赖对象的时候才开启相应对象的实例化阶段;而如果我们不是选择懒加载的方式,容器启动阶段完成之后,将立即启动Bean实例化阶段,通过隐式的调用所有依赖对象的getBean方法来实例化所有配置的Bean并保存起来。

1、对象创建策略:对象的创建采用了策略模式,BeanDefinationRegistry中的BeanDefination,我们可以使用反射的方式创建对象,也可以使用CGlib字节码生成创建对象。

2、BeanWrapper:由于Spring IOC容器为了统一对不同类型对象的访问,Spring给所有创建的Bean实例穿上了一层外套BeanWrapper。

BeanWrapper实际上是对反射相关API的简单封装,我们要获取某个对象的属性、调用某个对象的方法,现在不需要在写繁杂的反射API了以及处理一堆麻烦的异常,直接通过BeanWrapper就可以完成相关操作。

3、设置对象属性:对于基本类型的属性,如果配置元信息中有配置,那么将直接使用配置元信息中的设置值赋值即可,即使基本类型的属性没有设置值,属性依然可以被赋予默认的初始化零值;对于引用类型的属性,Spring会将所有已经创建好的对象放入一个Map结构中,此时Spring会检查Map中是否已经有对应对象的实例了。如果有,那么直接注入,如果没有,那么Spring会暂时放下该对象的实例化过程,转而先去实例化依赖对象,再回过头来完成该对象的实例化过程。


这里有一个Spring中的经典问题,那就是Spring是如何解决循环依赖的?

4、检查Aware相关接口:用户自定义的对象想要依赖Spring中的相关对象,那么可以实现相应的Aware接口,Spring IOC容器就会为我们自动注入相关依赖对象实例。

对于BeanFactory来说:先检查相关的Aware接口,然后去Spring的对象池(也就是容器,也就是那个Map结构)中去查找相关的实例(例如对于ApplicationContextAware接口,就去找ApplicationContext实例),也就是说我们必须要在配置文件中或者使用注解的方式,将相关实例注册容器中,BeanFactory才可以为我们自动注入。而对于ApplicationContext,由于其本身继承了一系列的相关接口,所以当检测到Aware相关接口,需要相关依赖对象的时候,ApplicationContext完全可以将自身注入到其中,ApplicationContext实现这一步是通过——BeanPostProcessor。

在这里插入图片描述

例如ApplicationContext继承自ResourceLoader和MessageSource,那么当我们实现ResourceLoaderAware和MessageSourceAware相关接口时,就将其自身注入到业务对象中即可。

5、BeanPostProcessor前置处理:


BeanPostProcessor

前置处理就是在要生产的Bean实例放到容器之前,允许我们程序员对Bean实例进行一定程度的修改,替换等操作。ApplicationContext对于Aware接口的检查与自动注入就是通过BeanPostProcessor实现的,在这一步Spring将检查Bean中是否实现了相关的Aware接口,如果是的话,那么就将其自身注入Bean中即可。Spring中AOP就是在这一步产生对于原生对象的代理对象,然后将对源对象上的方法调用,转而使用代理对象的相同方法调用实现的。

6、自定义初始化逻辑:如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。

7、BeanPostProcess后置处理:与前置处理类似,这里是在Bean自定义逻辑也执行完成之后,Spring又留给我们的最后一个扩展点。我们可以在这里在做一些我们想要的扩展。

8、自定义销毁逻辑:这一步对应自定义初始化逻辑,同样有两种方式:

实现DisposableBean接口

配置destory-method参数。

这里一个比较典型的应用就是配置dataSource的时候destory-method为数据库连接的close()方法。

9、使用

10、调用回调销毁接口:Spring的Bean在为我们服务完之后,马上就要消亡了(通常是在容器关闭的时候),别忘了我们的自定义销毁逻辑,这时候Spring将以回调的方式调用我们自定义的销毁逻辑,然后Bean就这样走完了光荣的一生!

在这里插入图片描述



版权声明:本文为zs18753479279原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。