文章目录
1、spring容器
主要由spring-core,spring-beans,spring-context提供容器的支持。
2、ClassPathXmlApplicationContext容器初始化过程
2.1 最简单的使用示例
maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.10.RELEASE</version>
</dependency>
在resources下的spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="com.User"/>
</beans>
简单使用
package com;
import java.util.UUID;
/**
* @author yinyuming
* @date 2021-06-08 11:45
*/
public class User {
public String name = UUID.randomUUID().toString();
}
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
User user = context.getBean(User.class);
}
}
2.2 容器初始化流程
2.3 类图
入口构造
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
//初始化容器,使用父类AbstractApplicationContext的refresh方法实现
if (refresh) {
refresh();
}
}
2.4 核心抽象类AbstractApplicationContext
核心功能都是由AbstractApplicationContext的refresh方法实现的,其他子类则是实现了父类的一些模板方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 容器预先准备记录容器启动时间和标记 ,模板方法装载配置文件,创建environment并加载System.properties()及System.getenv()到environment中。
prepareRefresh();
// 创建bean工程,如果已经有则摧毁,实现了对beanDefinition的装载,拿到Bean工厂的时候,beanDefinition就好了,XmlBeanDefinitionReader来读取所有Bean的定义。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//为Bean工厂做准备, 配置bean工厂的标准上下问特性,如类装载器,postProcesser
prepareBeanFactory(beanFactory);
try {
//模板方法,在bean定义被加载后,提供一个修改容器BeanFactory的入口方法
postProcessBeanFactory(beanFactory);
// 在bean未开始实例化时,对Bean定义修改的入口,常见的执行bean工厂后处理器BeanFactoryPostProcessor等
invokeBeanFactoryPostProcessors(beanFactory);
// 注册用于拦截bean创建过程的BeanPostProcessors,(这里会先注册Bean的拦截器,也会调用getBean方法,)
registerBeanPostProcessors(beanFactory);
// 初始话messageResource消息,
initMessageSource();
// 初始化上下问时间广播
initApplicationEventMulticaster();
// 模板方法
onRefresh();
// 注册监听器
registerListeners();
//完成容器的初始化,里面preInstaniateSingleons会完成单例对象的创建,核心初始化,实例化所有剩余的非懒加载的单例。
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
//摧毁bean容器,
//....省略
}
}
3 Bean的初始化过程(AbstractApplicationContext.getBean())
3.1 Bean的声明周期
以下是 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean的一些核心流程
- 1、getSingleton获取单例,(3级缓存),SingletonFactories:单例对象工厂cache,earlySingletonObject,提前暴露的单例对象cache,singleObject,单例对象的
- 2、没有bean,就从objectFactory的获取bean,调用createBean创建实例,
- 3、createBean执行instantiateBean初始化
- 4、createBeanInstance生成实例
- 5、addSingletonFactory提前暴露给spring的object工厂,缓存
- 6、populateBean填充属性, (初始化后就是设置属性,会执行各种aware,切入织面的Bean后处理器)
- 7、Bean拦截器,Bean实例话之后postProcessAfterInstantiation,返回false,不设置属性
- 8、处理autowire,依赖注入,使用getBean,继续递归获取Bean
- 9、Bean后处理器,postProcessPropertyValues, 可以处理属性值
- 10、applyPropertyValues最后把收集到的MutablePropertyValues注入到bean实例上
- 11、填充完属性,初始化方法,initializeBean,
- 12、(initializeBean)invokeAwareMethods处理核心aware接口,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
- 13、(initializeBean)applyBeanPostProcessorsBeforeInitialization执行后处理器postProcessBeforeInitialization(@PostConstruct的实现也是在这里处理的,InitDestroyAnnotationBeanPostProcessor)
- 14、 (initializeBean)invokeInitMethods,执行InitializingBean,invokeCustomInitMethod(执行自定义的初始化方法,如xml配置的init-method)
- 15、(initializeBean)postProcessAfterInitialization 后处理器
- 16、bean摧毁
3.2 bean的构造函数选择
以下是一些核心流程,源码位置:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
- 1、选择BeanDefinition的InstanceSupplier
- 2、选择BeanDefinition的FactoryMethodName(xml中配置factory-method属性)
- 3、走SmartInstantiationAwareBeanPostProcessor切入类获取构造函数,
(@Autowired注解构造函数处理,通过切入类AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors,获取有注解的构造函数,确认返回的构造函数,如果有两个Autowired注解会报错 ) - 4、选择clazz.getDeclaredConstructor()默认构造函数
3.3 bean的初始化过程切入类BeanPostProcessor
- BeanPostProcessor:初始化方法前后切入
- DestructionAwareBeanPostProcessor:摧毁前切入
- SmartInstantiationAwareBeanPostProcessor:构造重写,切入bean工厂或则返回指定的构造函数构造
- MergedBeanDefinitionPostProcessor:构造后收集属性,用于收集bean和beanDefinition
比如:AutowiredAnnotationBeanPostProcessor就是MergedBeanDefinitionPostProcessor收集属性,然后注入属性时,通过收集的属性注入
3.4 bean初始化循环依赖的处理
- 构造函数循环依赖
不支持 - 属性注入循环依赖,通过三级缓存解决循环依赖
Spring通过三级缓存解决了循环依赖,其中一级缓存为单例池(singletonObjects),二级缓存为早期曝光对象earlySingletonObjects,三级缓存为早期曝光对象工厂(singletonFactories)。
当A、B两个类发生循环引用时,在A完成实例化后,就使用实例化后的对象去创建一个对象工厂,并添加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。当A进行属性注入时,会去创建B,同时B又依赖了A,所以创建B的同时又会去调用getBean(a)来获取需要的依赖,此时的getBean(a)会从缓存中获取,第一步,先获取到三级缓存中的工厂;第二步,调用对象工工厂的getObject方法来获取到对应的对象,得到这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。当B创建完后,会将B再注入到A中,此时A再完成它的整个生命周期。至此,循环依赖结束!