文章篇幅较长,会针对于生命周期中的各个时期进行实例演示以及源码讲解。
Spring组织架构
在Spring中,Bean生命周期从流程上来分析大概可以得到上面的图片,各个环节涉及到的对象大概如下图:
Spring Bean生命周期
下面我们对每一个环节来进行具体分析:
读取Bean定义
元信息读取
我们要创建一个Bean,首先第一步就要知道Bean的元信息,在Spring中,主要提供了四种读取Bean元信息的方式,分别是Xml、Properties、Groovy和Annotated。读取方式都特别简单:
public class ParseBeanDefinitionDemo {
@Bean
public String str() {
return "annotated source";
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// xml方式读取
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(factory);
xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/xml-bean-definition-reader.xml");
// properties方式读取
PropertiesBeanDefinitionReader propertiesBeanDefinitionReader = new PropertiesBeanDefinitionReader(factory);
propertiesBeanDefinitionReader.loadBeanDefinitions("/META-INF/properties-bean-definition-reader.properties");
// groovy方式读取
GroovyBeanDefinitionReader groovyBeanDefinitionReader = new GroovyBeanDefinitionReader(factory);
groovyBeanDefinitionReader.loadBeanDefinitions("/META-INF/groovy-bean-definition-reader.groovy");
// 注解方式读取
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(factory);
annotatedBeanDefinitionReader.register(ParseBeanDefinitionDemo.class);
}
}
我们来简单看一下他的UML类图:
image-20230422090847726
从上图我们可以看到,Xml、Properties、Groovy的读取方式都继承了AbstractBeanDefinitionReader
,而使用注解方式的没有继承而是有单独的实现,其实这个也很好理解,因为前三个都是读取的外部化文件进行解析获取,所以有统一读取的规范,而注解是直接嵌插在Java代码中的,所以与前三个读取方式会有所不同。
Xml注册中的语法我们已经很熟悉,而对于Properties和Groovy的我们可以参考各个读取实现对象上面的注释,而一般情况我们也不会用到这两种读取方式。
image-20230422091831812
元信息注册
读取到Bean得元信息之后就需要把Bean的元信息注册到BeanFactory中,而Bean主要是使用BeanDefinitionRegistry#registerBeanDefinition()
方法进行注册。
Bean元信息注册有个工具类BeanDefinitionReaderUtils
,我们来看一下他注册BeanDefinition
的方法:
BeanDefinitionReaderUtils:BeanDefinitionReaderUtils():
image-20230422093421425
一个BeanFactory的实例对象通常还是一个Bean元信息的注册对象,所以上面的BeanDefinitionRegistry
通常就是一个IOC容器对象,我们拿DefaultListableBeanFactory
的容器对象来看(他是IOC容器,但是本身也是是一个BeanDefinitionRegistry
)
image-20230422093013200
获取Bean实例
如果说读取Bean定义为Bean实例化的准备阶段,那么获取Bean实例阶段就是创建Bean对象以及管理Bean生命周期中最重要的阶段。他的核心代码主要是在AbstractBeanFactory#doGetBean()
方法中,接下来我们的所有步骤都是围绕着这个方法展开讲解的。
我们先来看看doGetBean
方法中针对于 创建对象 过程中几个比较重要的关键步骤:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// .....
try {
// 合并并检查Bean定义信息
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Create bean instance.
// 创建单例对象
if (mbd.isSingleton()) {
// 获得单例对象
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建原型对象
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 获得原型对象
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// .....
return (T) bean;
}
上面主要包含两个步骤:1、合并Bean得元信息定义;2、校验单例或者原型模式创建对象,我们逐一进行分析。
合并Bean定义
为什么需要合并Bean定义呢?因为在xml中可能会存在如下定义(也就需要是将user中的定义合并到supperUser中,具体怎么使用这里就不演示了):
<bean name="user" class="com.phshi.entity.User">
<property name="name" value="zhansan"/>
<property name="sex" value="1"/>
</bean>
<!-- parent情况 -->
<bean name="supperUser" class="com.phshi.entity.SupperUser" parent="user">
<property name="specialAbilities" value="飞行"/>
</bean>
从上面doGetBean
的方法中我们可以看到,合并的入口是getMergedLocalBeanDefinition()
方法,接下来我们来看一下合并过程的具体逻辑:
AbstractBeanFactory#getMergedLocalBeanDefinition(String beanName)
:
// 存储合并过后的Bean定义信息的RootBeanDefinition集合
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 通过名称取出Bean得定义信息
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
// 如果不是空并且校验是否需要重新合并
if (mbd != null && !mbd.stale) {
return mbd;
}
// 合并逻辑 getBeanDefinition(beanName)就是获取未合并之前的bean定义
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
创建合并过程:
AbstractBeanFactory#getMergedBeanDefinitiongetMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
:
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
// 记录需要返回的RootBeanDefinition
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// 再校验一次状态
if (mbd == null || mbd.stale) {
previous = mbd;
// 校验是否包含parentName 不包含就不用合并 包含才需要合并
if (bd.getParentName() == null) {
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// 合并逻辑
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 取出parentBean的RootBeanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// 如果beanName和parentBeanName相同,则去ParentBeanFactory中获取beanDefinition进行合并
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
// 具体的合并逻辑 具体就是一些复制的逻辑,这里就不展开看了
mbd.overrideFrom(bd);
}
// ....
return mbd;
}
}
在Bean的定义信息合并完成之后,我们就会获得RootBeanDefinition
,接下来,我们就会使用这个RootBeanDefinition
进行创建对象。
创建对象实例
在前文代码中我们可以看到,在doGetBean()
方法中创建对象会根据作用域的不同来进行创建,在但是都会执行一个核心方法createBean()
,在这里我们就拿单例作用域来进行讲解。
我们可以看到单例创建对象的方法主要如下:
if (mbd.isSingleton()) {
// 注意后面是一个ObjectFactory的匿名内部类,创建对象的逻辑主要就是集中在createBean中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
我们先来简单看一下getSingleton()
方法:
getSingleton(String beanName, ObjectFactory<?> singletonFactory):
// singleton对象的缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 先从singletonObjects对象中获取
Object singletonObject = this.singletonObjects.get(beanName);
// singletonObjects对象中未取到才进行对象创建
if (singletonObject == null) {
// 可以作为循环引用的校验
beforeSingletonCreation(beanName);
try {
// 核心:调用匿名函数创建对象
singletonObject = singletonFactory.getObject();
} catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加到singletonObjects中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
生命周期中最核心的方法入口:
下面我们来看看创建对象的核心方法createBean
:
createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args):
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 1、获得Class对象,就是指定ClassLoader进行加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 2、进行方法重写
mbdToUse.prepareMethodOverrides();
// 3、执行实例化前的后置处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
// 4、创建实例对象
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
获得Class对象
创建对象前最重要的一步就是使用ClassLoader去加载从而获得Class对象,而在Spring中,使用ClassLoader加载获得Class对象主要是集中在createBean
方法中标记的第一步resolveBeanClass
这个方法中。
resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch):
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
// 校验对象类型是否是Class类型 this.beanClass instanceof Class
// this.beanClass是一个Object对象,比如xml配置的一般一开始对象类型都是String的
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// ...
return doResolveBeanClass(mbd, typesToMatch);
}
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
// 使用两个加载器的区别:
// beanClassLoader会使上一步的this.beanClass变成Class对象从而不会再进行重新加载
// dynamicLoader不会变this.beanClass从而每次实例化都需要进行重新加载class
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
// 使用临时类加载器
ClassLoader tempClassLoader = getTempClassLoader();
}
String className = mbd.getBeanClassName();
// 使用动态加载器进行加载
if (className != null) {
Object evaluated = evaluateBeanDefinitionString(className, mbd);
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
}
else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
if (freshResolve) {
if (dynamicLoader != null) {
try {
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
return ClassUtils.forName(className, dynamicLoader);
}
}
// 加载存入缓存
return mbd.resolveBeanClass(beanClassLoader);
}
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
// 存储到了beanClass中
this.beanClass = resolvedClass;
return resolvedClass;
}
createBean
方法中的第二步prepareMethodOverrides
主要是对bean标签中配置的lookup-method
以及属性replaced-method
进行重写覆盖。代码比较少也比较简单,这里就不进行讲解。
执行实例化前后置处理器
该步骤存在的主要意义是借助BeanPostProcessors给我们想要创建的Bean一个返回代理对象而不是目标bean实例的机会。该方式的核心就是InstantiationAwareBeanPostProcessor
接口。他也是Bean生命周期中一个非常重要的接口,提供了实例化前、实例化后以及属性赋值相关的处理方法。
- • 下面我们先来进行简单演示使用方式:
public class BeanPostProcessorsBeforeInstantiationDemo implements InstantiationAwareBeanPostProcessor {
@Bean(name="str")
public String str(){
return "这是我原来注册是值";
}
public static void main(String[] args) {
AnnotationConfigApplicationContext factory = new AnnotationConfigApplicationContext();
// 注册后置处理器
factory.addBeanFactoryPostProcessor(process->process.addBeanPostProcessor(new BeanPostProcessorsBeforeInstantiationDemo()));
factory.register(BeanPostProcessorsBeforeInstantiationDemo.class);
factory.refresh();
// 打印:str = 我是改变后的值
System.out.println("str = " + factory.getBean(String.class));
factory.close();
}
/**
* 初始化方法前的后置处理
* 如果返回不是空则对象为现在返回的对象,如果为空则继续进行下面的创建
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName,"str") && String.class.equals(beanClass)) {
return "我是改变后的值";
}
return null;
}
}
- • 下面我们来看看源码
resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd):
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果不为空的则直接执行初始化的后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 遍历所有的BeanPostProcessor并筛选出InstantiationAwareBeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
上面的代码少并且超级简单,这里就不在过多概述了。
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
的价值就在于拦截指定的Bean然后可以返回一个我们想要的对象或者是代理对象,在Spring中AOP动态代理就是接这个方式进行实现的,具体详情可以参考AbstractAutoProxyCreator
。
实例化
在执行完Bean的实例化前后置处理器之后,便要开始进行实例化了,首先我们先来看一下doCreateBean
方法中的主要功能。
doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args):
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Bean实例的包装对象
BeanWrapper instanceWrapper = null;
// 1、创建对象实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
// 2、执行后置处理合并Bean得定义信息
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// 中间还有一个执行SmartInstantiationAwareBeanPostProcessor处理的地方,但是Spring标注为了专用接口,为框架内部解决循环引用使用,这里就忽略了
// 3、对bean的属性进行填充
populateBean(beanName, mbd, instanceWrapper);
// 4、执行bean的初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 5、注册Bean的信息方便Bean销毁时候使用
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
首先来看第一步,创建实例对象,在Spring中,如果不规定创建对象的方法的话,主要是会使用了CGLIB或者是JDK动态代理两种方式对对象进行实例化。整体来看这个创建对象的过程还是比较复杂的,对其我们就不深入追究了,我们就简单来看一下createBeanInstance
方法。
createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args):
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获得Class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 使用Supplier创建对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 使用工厂方法创建对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 使用有参构造方法创建
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 使用默认无参构造方法创建
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 通过CGlib或者JDK动态代理创建对象
return instantiateBean(beanName, mbd);
}
执行Bean定义信息处理器
上一步结束,我们的对象就已经被创建完成了,当然,现在的他还只是一个最原生的对象,当然,现在他可以被使用,只不过他还未进行属性赋值,也就是说,他的所有属性现在都还是空的。所以按照流程来讲,下一步我们就是对上一步创建出来的对象进行赋值。
实际上,在对对象赋值之前还有一个步骤要进行处理。Spring留了一步,允许我们在对属性赋值前有一个机会去修改Bean的定义信息。修改方式Spring也是使用了
BeanPostProcessor
这种后置处理的方式。Spring中提供了一个BeanPostProcessor
的子类MergedBeanDefinitionPostProcessor
专门用来修改或者是重新重制Bean得一些定义信息。
我们先来演示一下他的使用方式:
使用方式:
public class MergedBeanDefinitionPostProcessorDemo implements MergedBeanDefinitionPostProcessor {
@Bean
public User user() {
User user = new User();
user.setName("lisi");
user.setSex(0);
return user;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 使用了AnnotationConfigApplicationContext可以不用手动注册PostProcessor
// applicationContext.addBeanFactoryPostProcessor(process -> process.addBeanPostProcessor(new MergedBeanDefinitionPostProcessorDemo()));
applicationContext.register(MergedBeanDefinitionPostProcessorDemo.class);
applicationContext.refresh();
User user = applicationContext.getBean(User.class);
// 打印的:name='王武', sex=1 而不是 name='lisi', sex=0
System.out.println("user = " + user);
applicationContext.close();
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ObjectUtils.nullSafeEquals(beanName, "user") && User.class.equals(beanType)) {
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.add("name", "王武");
propertyValues.add("sex", 1);
}
}
}
我们再来看看他在Spring中的源码:
源码:
applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName):
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 校验Process是否是MergedBeanDefinitionPostProcessor类型
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
代码也很简单,遍历所有的process方法,获取到MergedBeanDefinitionPostProcessor
类型的处理器并执行postProcessMergedBeanDefinition
方法。
MergedBeanDefinitionPostProcessor
执行的代码虽然简单,但是在Spring中却扮演着重要的角色,我们常常用到的@Autowired
或者是@Resource
注入的属性就是在这里被扫描到并存储起来用于后面注入的,这里就不展开讲了,后面有机会我们在来讲解相关知识。
填充Bean属性
当我们最后一次允许修改Bean定义信息之后,那么相当于我们Bean得定义信息就已经确认好了,接下来我们就可以放心的进行属性的填充。属性填充随着填充方式多样,所以代码也比较多,主要集中在AbstractAutowireCapableBeanFactory#populateBean()
方法中,我们先整体来看一下这个方法。
populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw):
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 1、使用InstantiationAwareBeanPostProcessor进行直接注入,返回false跳过后续自动注入过程
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 2、校验注入模式是否是自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 2.1、按照名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 2.2、按照类型自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 3、使用InstantiationAwareBeanPostProcessor中提供的方法进行注入
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 该方法已经设置为废弃,被postProcessProperties代替
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
// 4、属性设置 上面三步其实都只是将属性值设置到PropertyValues中,这步才将值进行赋值到对象上
applyPropertyValues(beanName, mbd, bw, pvs);
}
从上面的代码分析中我们大概可以看出注入大概分为四种方式:
- • 通过实例化后置处理器
InstantiationAwareBeanPostProcessor
的postProcessAfterInstantiation
方法进行直接注入(该注入方式可以跳过后面的自动注入) - • 通过类型或者名称自动注入
- • 通过
InstantiationAwareBeanPostProcessor
的postProcessProperties
方法或者是postProcessPropertyValues
方法进行注入(后面的方法已经弃用) - • 属性值设置方式(包含基本类型注入以及引用类型注入,其实上面三步是将值设置到
PropertyValues
中,而这步是将PropertyValues
的值设置到对象中)
下面我们一个一个的分析上面四种注入方式:
实例化后置处理器注入
首先,我们先来看看实例化后置处理器注入的使用方式。
使用方式:
public class PostProcessAfterInstantiationDemo implements InstantiationAwareBeanPostProcessor {
@Bean
public User user() {
User user = new User();
user.setName("lisi");
user.setSex(0);
return user;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 使用了AnnotationConfigApplicationContext可以不用手动注册PostProcessor
// applicationContext.addBeanFactoryPostProcessor(process -> process.addBeanPostProcessor(new PostProcessAfterInstantiationDemo()));
applicationContext.register(PostProcessAfterInstantiationDemo.class);
applicationContext.refresh();
User user = applicationContext.getBean(User.class);
// 打印的:name='王武', sex=1 而不是 name='lisi', sex=0
System.out.println("user = " + user);
applicationContext.close();
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "user") && User.class.equals(bean.getClass())) {
User user = (User) bean;
// 进行属性赋值替换
user.setName("王武");
user.setSex(1);
return false;
}
return true;
}
}
对于源码也比较简单,就是populateBean
方法中的第一步,这里就不再单独列出来一次了。
通过类型或名称自动注入
这种自动注入的方式主要针对于的是引用的数据类型,基本类型是不支持自动注入的。
通过类型注入通常是使用xml配置的,使用起来也比较简单,我们就不进行演示了。我们直接来看看注入的实现原理吧!
通过名称注入:
autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs):
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历所有的属性
for (String propertyName : propertyNames) {
// 使用名称去BeanFactory容器中查询是否存在这个Bean
if (containsBean(propertyName)) {
// 通过Bean名称去容器中获取对象
Object bean = getBean(propertyName);
// 设置值
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
通过名称注入就比较简单了,校验IOC容器中是否存在指定名称的Bean,如果存在取出来设置进去就ok了。
通过类型注入:
autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs):
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历所有的属性
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 核心就是这里的按照类型进行依赖查找 该方法在前面的依赖注入方法进行了详细讲解
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// 查询到则设置值
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
上面代码看着虽然多,但是最核心其实就是resolveDependency
方法,该方法会按照类型去查找对应的Bean对象,该方法在前面章节 Spring依赖注入(二) - 注入过程 进行了详细讲解。
postProcessProperties方法
该方式注入可以算是注入方式的一个扩展,他支持了第三方或者些复杂的方式注入,比如@Autowired
或者是@Resource
注入都是在这一步完成的。下面我们先来看一下他的使用方式。
使用方式:
这里只演示postProcessProperties
方法,postProcessPropertyValues
方法使用方式和这个类似,就不进行演示了
public class PostProcessPropertiesDemo implements InstantiationAwareBeanPostProcessor {
@Bean
public User user() {
User user = new User();
user.setName("lisi");
user.setSex(0);
return user;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 使用了AnnotationConfigApplicationContext可以不用手动注册PostProcessor
// applicationContext.addBeanFactoryPostProcessor(process -> process.addBeanPostProcessor(new PostProcessPropertiesDemo()));
applicationContext.register(PostProcessPropertiesDemo.class);
applicationContext.refresh();
User user = applicationContext.getBean(User.class);
// 打印的:name='王武', sex=1 而不是 name='lisi', sex=0
System.out.println("user = " + user);
applicationContext.close();
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "user") && User.class.equals(bean.getClass())) {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("name","王武");
propertyValues.addPropertyValue("sex",1);
return propertyValues;
}
return pvs;
}
}
具体这块的源代码实现也很简单,这里也就不单独列出来了。
属性值设置
这一步可以说是整个属性填充最重要的一步,前面三步其实相当于将属性的值都设置到了PropertyValues
中,这一步中会将PropertyValues
中取出来填充到我们实例化处理的对象中。
applyPropertyValues
方法前面的步骤其实都是为了处理类型转化,比如我们在xml里面配置的是String类型,但是我们最终却可以注入到Integer类型中其实就是在这一步中进行了数据转化,
该方法大概可以分为三个步骤:
- • 输入对象类型的转化
- • 通过可写方法(set方法)的入参类型进行转化
- • 给对象赋值
我们先来简单的看一下他的代码:
applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs):
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// 如果已经完成了类型转化的话可以进行直接赋值。 在下文转化完了之后修改了状态为转化完成
if (mpvs.isConverted()) {
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
// 获取自定义类型转化器(一般都是null)
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 获得类型解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 需要将填入对象进行深拷贝,以免出现问题
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
// 校验是否需要转化
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
// 获得转化的属性名与属性值
String propertyName = pv.getName();
Object originalValue = pv.getValue();
// 进行类型转化
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
// 校验转化的字段是否可写
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 再使用set方法再进行一次类型转化 String转化为Integer就是在这处理的
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
}
}
if (mpvs != null && !resolveNecessary) {
// 设置完成了类型转化
mpvs.setConverted();
}
// 设置属性 最终其实执行writeMethod.invoke(getWrappedInstance(), value)反射赋值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
- • 1、
resolveValueIfNecessary(Object argName, @Nullable Object value):
该方法通过各种传入数据不同类型判断然后走不通的数据转化方法(具体不列出转化方式,具体可以去对象BeanDefinitionValueResolver#resolveValueIfNecessary()
中查看该方法):
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
if (value instanceof RuntimeBeanReference) {
}
else if (value instanceof RuntimeBeanNameReference) {
}
else if (value instanceof BeanDefinitionHolder) {
}
else if (value instanceof BeanDefinition) {
}
else if (value instanceof DependencyDescriptor) {
}
else if (value instanceof ManagedArray) {
}
else if (value instanceof ManagedList) {
}
else if (value instanceof ManagedSet) {
}
else if (value instanceof ManagedMap) {
}
else if (value instanceof ManagedProperties) {
}
else if (value instanceof TypedStringValue) {
}
else if (value instanceof NullBean) {
}
else {
return evaluate(value);
}
}
protected Object evaluate(@Nullable Object value) {
if (value instanceof String) {
}
else if (value instanceof String[]) {
}
else {
return value;
}
}
上一步结束只是对对象类型进行了一个简单的转化,并不会将String转化为Integer或者是将资源路径转化资源对象。而这个转化是在下一步convertForProperty
中进行的。
- • 2、
convertForProperty(@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter):
@Nullable
private Object convertForProperty(
@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
if (converter instanceof BeanWrapperImpl) {
return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
}
else {
// 获得可写方法
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// 类型转化
return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
}
}
@Nullable
public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
// 获得propertyName属性相关的属性类型信息,包括写(set)和读(get)方法
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
if (pd == null) {
throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
"No property '" + propertyName + "' found");
}
// 获得设置的对象的具体类型
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
if (td == null) {
td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
}
// 类型转化
return convertForProperty(propertyName, null, value, td);
}
- • 3、最后的
bw.setPropertyValues
方法便是给对象进行属性赋值
这一步方法嵌套比较深看着比较复杂,但是整体来看逻辑很简单,就是拿到可写方法(set方法),然后使用writeMethod.invoke(getWrappedInstance(), value)
放射进行复制,详情可以自己去追踪源码查看。
Bean的属性赋值整体来说很复杂,尤其是类型转化,可以说是整个生命周期中最复杂的步骤了,而对于类型转化
TypeDescriptor
也只是随便说了几句,因为它本身就是一个很复杂的东西,不是这里讲解的重点,后面如果有机会我们会进行相关的讲解。
执行Bean初始化方法
Bean的属性赋值结束,那么接下来的就都比较轻松了。Bean实例化好并且属性赋值完毕,下一步就是开始执行Bean相关的初始化方法。在源码中,这一块代码是在
AbstractAutowireCapableBeanFactory.initializeBean()
,在这一步中,我们可以划分为如下几个步骤:
- • 执行Aware接口
- • 执行
BeanPostProcessor
的初始化前的后置处理器- • 执行
InitializingBean
的afterPropertiesSet
方法- • 执行xml中配置的
init-method
方法- • 执行
BeanPostProcessor
的初始化后的后置处理器
首先,我们依旧是先整体来看一下这一块的代码:
initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd):
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 执行Aware接口方法
invokeAwareMethods(beanName, bean);
// 执行 BeanPostProcessor 的初始化前的后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 执行初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
// 执行 BeanPostProcessor 的初始化后的后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
执行Aware接口
首先我们来回顾一下Aware接口有哪些:
接口名称 | 描述 |
BeanFactoryAware | 获取 IoC 容器 - BeanFactory |
ApplicationContextAware | 获取 Spring 应用上下文 - ApplicationContext 对象 |
EnvironmentAware | 获取 Environment 对象 |
ResourceLoaderAware | 获取资源加载器 对象 - ResourceLoader |
BeanClassLoaderAware | 获取加载当前 Bean Class 的 ClassLoader |
BeanNameAware | 获取当前 Bean 的名称 |
MessageSourceAware | 获取 MessageSource 对象,用于 Spring 国际化 |
ApplicationEventPublisherAware | 获取 ApplicationEventPublishAware 对象,用于 Spring 事件 |
EmbeddedValueResolverAware | 获取 StringValueResolver 对象,用于占位符处理 |
Aware相关的接口主要就是上面几个,我们在 Spring依赖注入(一) - 注入方式 章节讲解过,页演示了怎么使用,这里就再演示了,记不得的可以回去回顾一下。
我们下面还是从源码看是看吧:
invokeAwareMethods(String beanName, Object bean):
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
// 执行 BeanNameAware 接口方法
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 执行 BeanClassLoaderAware 接口方法
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// 执行 BeanFactoryAware 接口方法
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
从上面方法中我们9个Aware接口却只执行了3个,这是为什么呢?其实原因很简单,现在当前对象是
BeanFactory
,说具体一点是DefaultListableBeanFactory
,而在这九个Aware接口中他能拿到的数据也只有这三个,另外6个都是依赖于ApplicationContext
的,但是DefaultListableBeanFactory
又拿不到ApplicationContext
的信息,所以其他九个就不在这里执行。
那么另外6个不在这里执行在哪执行呢?由于是执行Aware接口,这里我们就提前说明,其实另外六个是在初始化前的后置处理器中进行,这里我们先来提前看一下ApplicationContextAwareProcessor
这个处理器中的初始化前的后置处理方法。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 如果不属于这些接口则返回
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
// 属于则设置对应值
invokeAwareInterfaces(bean);
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
执行初始化前的后置处理器
在上一步中我们也看到了初始化前后置处理器的一种使用方式,而初始化前的后置处理器执行源码也非常简单:
applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName):
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
虽然上一步我们看到了关于
applicationContext
相关的Aware接口在初始化前的后置处理器中执行了,但是他在Spring中的使用也不仅仅如此,比如我们在@PostConstruct
进行初始化或者是@PreDestroy
进行销毁也是采用这种方式去实现的,具体实现的可以去InitDestroyAnnotationBeanPostProcessor
对象中进行查看。
执行初始化方法
在 Spring Bean基础 中我们讲到过,对象的初始化主要有三种方式:
- •
@PostConstruct
注解 - • 实现 InitializingBean 接口的 afterPropertiesSet() 方法
- • 使用@Bean或者xml中initMethod定义的初始化方法
而那时候我们也说明了他们三个执行的先后顺序是:@PostConstruct -> InitializingBean -> @Bean
我们先来用一个案例来进行说明:
public class User implements InitializingBean {
private String name;
private Integer sex;
// .... get、set、toString方法
@PostConstruct
public void init() {
System.out.println("@PostConstruct初始化执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean中的afterPropertiesSet方法执行");
}
public void initMethod() {
System.out.println("initMethod方法执行!");
}
}
public class BeanInstantiationInitDemo {
@Bean(value = "user", initMethod = "initMethod")
public User user() {
return new User();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(BeanInstantiationInitDemo.class);
applicationContext.refresh();
System.out.println("applicationContext.getBean(User.class) = " + applicationContext.getBean(User.class));
applicationContext.close();
}
}
执行结果:
@PostConstruct初始化执行
InitializingBean中的afterPropertiesSet方法执行
initMethod方法执行!
applicationContext.getBean(User.class) = User{name='null', sex=null}
接下来我们就进入源码来看一下这个执行顺序的原因:
@PostConstruct
注解:
上面也说了,在Spring中存在一个后置处理器叫做InitDestroyAnnotationBeanPostProcessor
,他专门处理通过注解实现的初始化方式,我们通过代码来看一下他的几个重要部分:
- 1. 筛选并记录被标记为初始化/销毁的方法
public class InitDestroyAnnotationBeanPostProcessor {
// 标记初始化和销毁注解
@Nullable
private Class<? extends Annotation> initAnnotationType;
@Nullable
private Class<? extends Annotation> destroyAnnotationType;
// 在执行Bean定义信息后置处理器时筛选出被指定注解标注的方法
// 最后标记的初始化和销毁存储在LifecycleMetadata中
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
// 缓存中不存在就直接去构建
if (this.lifecycleMetadataCache == null) {
return buildLifecycleMetadata(clazz);
}
// 缓存中存在尝试从缓存中获取
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
// ...
return metadata;
}
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
// 先校验对象方法中是否包含对应注解标注的方法
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
// 下面就是将初始化和销毁方法封装为LifecycleElement,然后存储到LifecycleMetadata中
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
}
- 1. 执行标记了初始化和销毁的方法
public class InitDestroyAnnotationBeanPostProcessor {
// 在初始化前后置处理器中进行执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 执行了LifecycleMetadata中的invokeInitMethods方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
}
那我们看一下LifecycleMetadata#invokeInitMethods
方法:
private class LifecycleMetadata {
// 第一步中存储的初始化以及销毁方法,一个对象中可以有多个
private final Collection<LifecycleElement> initMethods;
private final Collection<LifecycleElement> destroyMethods;
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
// 遍历执行所有的初始化方法
for (LifecycleElement element : initMethodsToIterate) {
// 内部就是执行 method.invoke(target, (Object[]) null)方法
element.invoke(target);
}
}
}
}
我们看到了使用注解去执行方法的实现,却没有看到@PostConstruct
和@PreDestroy
这两个注解,其实是因为@PostConstruct
和@PreDestroy
两个注解是在CommonAnnotationBeanPostProcessor
中定义的,而CommonAnnotationBeanPostProcessor
实现了InitDestroyAnnotationBeanPostProcessor
,定义的详情我们可以在CommonAnnotationBeanPostProcessor
构造器中看到。
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor{
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
}
}
实现 InitializingBean 接口的 afterPropertiesSet() 方法:
这种实现比上面的就简单的很多很多,我们一看代码就知道了
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 看看对象是否继承InitializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
// 继承则强转并执行afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
// 使用@Bean或者xml中initMethod定义的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
使用@Bean或者xml中initMethod定义的初始化方法:
该方式实现也是比较简单的:
invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd):
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
// 获得配置的初始化方法名称
String initMethodName = mbd.getInitMethodName();
// 通过名称获得Method对象
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
// 反射执行
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
本节一开头就讲了并且演示了三种初始化方法的执行顺序是
@PostConstruct -> InitializingBean -> @Bean
,从源码层面我们也看出来了,由于基于注解的初始化方法是在初始化前的后置处理器InitDestroyAnnotationBeanPostProcessor
中执行的,所以注解方式最先执行,然后是校验了对象是否实现了InitializingBean
接口,如果实现执行afterPropertiesSet
方法,所以InitializingBean
第二执行,最后才是在invokeCustomInitMethod
方法中执行自定义的初始化方法。
执行初始化后的后置处理器
初始化后的后置处理器执行方式和初始化前的后置处理器差不多,代码超级简单,我们看一下就清楚了:
applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName):
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
到这里结束,我们的一个对象的创建生命周期就算是结束了,这个对象就可以正常使用了。
Bean的销毁
Bean在上一步结束我们就拿到手使用了,但是至此Bean的生命周期并没有结束,一个单例Bean处理具有创建实例过程的生命周期(原型只有创建时的生命周期,没有销毁的生命周期),还具有销毁的生命周期,接下来我们就看一下一个Bean的销毁处理过程。
其实一个Bean的销毁过程经历和初始化这个过程时相似的,只不过前者是为了初始化,后者是为了销毁。
销毁也可以分为三个步骤:
- • 执行销毁前的后置处理器 -
@PreDestroy
注解处理方式 - • 执行
DisposableBean
对象的destroy()
方法 - • 执行自定义的
destroyMethod
我们先来用一个案例来进行说明:
public class User implements InitializingBean, DisposableBean {
private String name;
private Integer sex;
// .... get、set、toString方法
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy销毁执行");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean中的destroy方法执行");
}
public void destroyMethod (){
System.out.println("destroyMethod方法执行!");
}
}
public class BeanInstantiationDestroyDemo {
@Bean(value = "user", initMethod = "destroyMethod")
public User user() {
return new User();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(BeanInstantiationDestroyDemo.class);
applicationContext.refresh();
System.out.println("applicationContext.getBean(User.class) = " + applicationContext.getBean(User.class));
applicationContext.close();
}
}
执行结果:
applicationContext.getBean(User.class) = User{name='null', sex=null}
@PreDestroy销毁执行
DisposableBean中的destroy方法执行
destroyMethod方法执行!
我们可以看到,销毁的过程其实可初始化的过程也是一样的:@PreDestroy->DisposableBean->destroyMethod
由于处理出过程比较简单,我们就整合在一起看了,下面我们通过源码来看一下:
销毁过程主要是在DisposableBeanAdapter
对象中:
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
@Override
public void destroy() {
// 1、执行销毁前后置处理器。@PreDestroy处理便是在这步进行,具体处理过程参考执行初始化方法中的过程
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
// 2、执行DisposableBean对象的destroy()方法
if (this.invokeDisposableBean) {
((DisposableBean) this.bean).destroy();
}
// 3、执行自定义的`destroyMethod`
invokeCustomDestroyMethod(this.destroyMethod);
}
private void invokeCustomDestroyMethod(final Method destroyMethod) {
int paramCount = destroyMethod.getParameterCount();
final Object[] args = new Object[paramCount];
if (paramCount == 1) {
args[0] = Boolean.TRUE;
}
// 通过反射执行自定义销毁方法
ReflectionUtils.makeAccessible(destroyMethod);
destroyMethod.invoke(this.bean, args);
}
}
Bean的销毁过程和执行初始化方法的过程是相同的,这个执行过程相对比较简单,我们只需要记住三种销毁方式的执行顺序是
@PreDestroy->DisposableBean->destroyMethod
就行
总结
整体来看Bean创建到销毁的整个生命周期还是比较复杂的,下面我们梳理一下Bean创建到销毁执行的相关方法顺序:
BeanDefinition处理:
- • AbstractBeanFactory#getMergedLocalBeanDefinition 合并Bean定义
- • AbstractBeanFactory#resolveBeanClass 获得Class对象
实例化阶段:
- • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 实例化前后置处理
- • 实例化
- • MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition BeanDefinition处理器
- • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 实例化前后置处理
- • InstantiationAwareBeanPostProcessor#postProcessProperties PropertyValues处理器
初始化阶段:
- • Aware 接口回调
- • BeanPostProcessor#postProcessBeforeInitialization 初始化前置处理
- • InitializingBean#afterPropertiesSet
- • 自定义initMethod方法
- • BeanPostProcessor#postProcessAfterInitialization 初始化后置处理
销毁阶段:
- • DestructionAwareBeanPostProcessor#postProcessBeforeDestruction 销毁前后置处理
- • DisposableBean#destroy
- • 自定义destroyMethod方法
注意:多例会有实例化及其实例化之前的所有操作,但是不会有销毁阶段的操作,因为我们不知道多例什么时候会被销毁。
扩展
我们知道,一个Bean在没有被声明成懒加载的形式的话,那么在项目启动的时候就会去加载然后创建好缓存所有的Bean,那么这个过程在那里实现呢?
答案是在DefaultListableBeanFactory
中的preInstantiateSingletons
方法会在项目启动的时候实例化所有(非惰性init)singleton bean。
我们来简单的看一下这个方法:
preInstantiateSingletons():
@Override
public void preInstantiateSingletons() throws BeansException {
// 获得所有的beanDefinition名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍历所有Bean定义信息然后对非懒惰单例bean进行初始化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 不是抽象的、单例的、不是懒加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
getBean(beanName);
}
}
}
单例与原型
单例是Spring中默认的Bean实现方式,在Spring中校验一个Bean是单例还是原型是通过BeanDefinition
来进行确认的,在我们使用BeanFactory#getBean
的时候,我们可以看到里面的实现就是通过判断isSingleton
和isPrototype
判断出创建的对象应该是单例还是原型。
下面是getBean
创建对象实例时最终会执行的部分代码(其中的mbd就是BeanDefinition
):
但是有一点需要我们去注意,单例由于在整个IOC容器中唯一,所以,Spring是会管理他完整的生命周期的,但是原型创建出对象后Spring就不知道改什么时候会被销毁,所以无法执行销毁方法回调。
其他作用域
除了单例与原型的作用域是通过BeanDefinition
校验之外,其他的作用域都是通过实现Scope
接口的方式来进行实现的。
request、session和application的作用域实现类分别是RequestScope
、SessionScope
和ServletContextScope
,RequestScope
是基于一次请求,所以他Bean是存储与ThreadLocal中,SessionScope
是基于会话,所以通过session-id
查找对应的Bean信息,而ServletContextScope
是直接将Bean存储在ServletContext
中,而他们注册是在WebApplicationContextUtils
进行的,对于三个作用域的实现逻辑也比较简单,感兴趣的可以自己下去看看。
WebApplicationContextUtils#registerWebApplicationScopes()
自定义作用域
实现一个作用域,基于线程内Bean是单例的。
自定义作用域:
public class ThreadScope implements Scope {
public static final String NAME = "threadScope";
// 存放于ThreadLocal中
private ThreadLocal<Map<String, Object>> tl = ThreadLocal.withInitial(() -> new HashMap<>());
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
// 基于线程id取,如果取不到则创建
Map<String, Object> map = tl.get();
Object o = map.get(getThreadId());
if (Objects.isNull(o)) {
o = objectFactory.getObject();
map.put(getThreadId(), o);
}
return o;
}
@Override
public Object remove(String name) {
return tl.get().remove(getThreadId());
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
// 基于线程id
return getThreadId();
}
private String getThreadId() {
return Thread.currentThread().getId() + "";
}
}
测试:
public class CustomBeanScopeDemo {
@Bean
@Scope(ThreadScope.NAME)
public ScopeEntity scopeEntity() {
return new ScopeEntity(System.currentTimeMillis(), "自定义作用域");
}
public static void main(String[] args) throws InterruptedException {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(CustomBeanScopeDemo.class);
// 注册作用域
annotationConfigApplicationContext.addBeanFactoryPostProcessor(beanFactory -> beanFactory.registerScope(ThreadScope.NAME, new ThreadScope()));
annotationConfigApplicationContext.refresh();
// 创建三个线程,校验是否每个线程中的对象都相等
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(() -> {
ScopeEntity bean1 = annotationConfigApplicationContext.getBean(ScopeEntity.class);
ScopeEntity bean2 = annotationConfigApplicationContext.getBean(ScopeEntity.class);
ScopeEntity bean3 = annotationConfigApplicationContext.getBean(ScopeEntity.class);
System.out.println(Thread.currentThread().getName() + "线程中bean1的值为:" + bean1);
System.out.println(Thread.currentThread().getName() + "线程中bean2的值为:" + bean2);
System.out.println(Thread.currentThread().getName() + "线程中bean3的值为:" + bean3);
}, "thread-" + i);
thread.start();
thread.join();
}
annotationConfigApplicationContext.close();
}
}