文章目录
1 前言
Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段,这里只讲解前2个阶段
2 BeanPostProcessor
BeanPostProcessor(Bean后置处理器)是一个接口,还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展。bean生命周期中的扩展点都是依靠BeanPostProcessor来实现的,所以如果大家想对bean的生命周期进行干预,这块一定要掌握好。
BeanPostProcessor接口是spring提供给开发者的扩展点,通过容器在Bean的生命周期的适当位置进行调用。
BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用,因此部署一个后置处理器同部署其他的bean并没有什么区别。而使用BeanFactory实现的时候,bean 后置处理器必须通过代码显式地去注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法。
BeanPostProcessor对所有该注册容器中的bean生效。
不管是BeanFactory还是ApplicationContext,BeanPostProcessors后置处理器被注册后,需要有个集合存储,这个集合是AbstractBeanFactory的属性。
/** BeanPostProcessors集合 */
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
/** post-processors缓存 */
@Nullable
private volatile BeanPostProcessorCache beanPostProcessorCache;
private class BeanPostProcessorCacheAwareList extends CopyOnWriteArrayList<BeanPostProcessor> {// 省略}
static class BeanPostProcessorCache {
final List<InstantiationAwareBeanPostProcessor> instantiationAware = new ArrayList<>();
final List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = new ArrayList<>();
final List<DestructionAwareBeanPostProcessor> destructionAware = new ArrayList<>();
final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
}
factory使用BeanPostProcessor通过BeanPostProcessorCache缓存获取,如果缓存不存在,会通过beanPostProcessors初始化缓存,在下面讲解bean实例化前阶段时,会通过源码具体了解该过程。
这里只是简单讲解了下BeanPostProcessor,为下面做铺垫,随着我们对BeanPostProcessor了解加深,我会专门写一篇关于BeanPostProcessor的内容。
和我们实例化前阶段相关的BeanPostProcessor为InstantiationAwareBeanPostProcessor。
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.lang.Nullable;
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* 实例化前执行该方法
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
*实例化之后执行该方法
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* 属性赋值之前执行该方法
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return pvs;
}
}
InstantiationAwareBeanPostProcessor通常用于抑制(修改)特定目标bean的默认实例化,给我们提供了三个扩展点:实例化bean之前、实例化之后、属性赋值之前。
- postProcessBeforeInstantiation():实例化bean之前扩展点,在目标bean开始实例化前触发该方法。返回的bean对象可能是要使用的代理,而不是目标bean,从而有效地抑制了目标bean的默认实例化。如果此方法返回非null对象,则bean创建过程将被短路(也就是正常bean实例化的后续流程不再执行)。
- postProcessAfterInstantiation():实例化后扩展点,在bean被实例化之后,通过构造函数或工厂方法。但在属性填充(from explicit properties or autowiring)发生之前,执行操作。这是在Spring的自动连接开始之前,在给定bean实例上执行自定义字段注入的理想回调。当然返回结果为true时,说明应该为bean设置属性。如果返回结果为false,跳过bean属性赋值环节。默认实现返回true。
- postProcessProperties():在工厂将给定的属性值应用于给定的bean之前,对其进行后处理,而不需要任何属性描述符。
下面我们来看下InstantiationAwareBeanPostProcessor在实例化前阶段的该如何使用。
3 bean实例化前阶段
3.1 postProcessBeforeInstantiation()在哪里被调用?
我们还是通过getBean()方法来追踪下,在哪里回执行InstantiationAwareBeanPostProcessor。
DefaultListableBeanFactory getBean()->AbstractBeanFactory doGetBean()->AbstractAutowireCapableBeanFactory createBean()
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 省略..
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 省略...
}
resolveBeforeInstantiation() 方法
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
applyBeanPostProcessorsBeforeInstantiation()方法
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
- 遍历缓存获取的InstantiationAwareBeanPostProcessor对象,实例化之前执行postProcessBeforeInstantiation()方法。
3.2 测试
自定义类MyInstantiation实现InstantiationAwareBeanPostProcessor接口。
package com.gaogzhen.myspring.processors;
import com.gaogzhen.myspring.bean.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
/**
* @author: Administrator
* @createTime: 2023/03/12 09:15
*/
public class MyInstantiation implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("user".equalsIgnoreCase(beanClass.getSimpleName())) {
User user = new User();
user.setName("张三");
return user;
}
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
}
- 如果beanClass类型为User.class,我们自己new User对象,并且设置name为“张三”
测试类:
@Test
public void testInstantiation() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.addPropertyValue("name", "xxx");
factory.registerBeanDefinition("user3", definitionBuilder.getBeanDefinition());
factory.addBeanPostProcessor(new MyInstantiation());
User user = factory.getBean("user3", User.class);
System.out.println(user);
}
测试方法中,我们设置bean的name为“xxx",看下测试结果
User{name='张三'}
- MyInstantiation对factory中所有bean生效。
- 实际上,在实例化前阶段对bean的创建进行干预的情况,用的非常少,所以大部分bean的创建还会继续走下面的阶段。
4 bean实例化
这个过程中,我们不仅要了解bean的实例化过程,更关心spring为我们开发者提供的扩展点。
4.1 实例化过程
继续跟踪之前的代码AbstractAutowireCapableBeanFactory 的createBean()方法
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 省略...
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// 省略...
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// 省略...
}
在我们对实例化前阶段对bean的创建不进行干预的情况下,继续执行doCreateBean()方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 省略
}
第一次创建bean,factoryBeanInstanceCache缓存中不会有instanceWrapper
- BeanWrapper:对bean实例包装,在其实现类有属性存放bean实例对象。
继续执行createBeanInstance()方法
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 省略..
// 自定义实现创建bean实例方法
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 通过工厂方法实例化bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 再次创建bean实例
// 省略...
// 扩展点,自定义确定bean构造器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// BeanDefinition中定义的构造器
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 使用默认无参构造器实例化bean
return instantiateBean(beanName, mbd);
}
- bean(初次)实例化5种方式,自上而下有优先级顺序,任何一种方式实例化bean返回
- 自己在BeanDefinition定义中提供实例化bean方式,为Supplier接口
- BeanDefinition定义中提供工厂方法,使用工厂方法实例化bean
- 通过spring提供的扩展点即实现SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors()方法确定bean的构造器,通过该构造器实例化bean
- BeanDefinition定义中提供构造器
- 使用无参构造器实例化bean
除第一种方法外,其他都是通过反射创建bean的实例。这里我们主要讲解下通过扩展来实例化bean的方式。
4.2 SmartInstantiationAwareBeanPostProcessor扩展
看下determineConstructorsFromBeanPostProcessors()方法
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
return null;
}
通过遍历BeanPostProcessor缓存的SmartInstantiationAwareBeanPostProcessor对象,执行determineCandidateConstructors()方法决定bean的构造器。
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
可以将@Autowired
标注的方法作为候选构造器返回,有兴趣的可以去看一下代码。
4.3 测试
bean Person
package com.gaogzhen.myspring.bean;
import com.gaogzhen.myspring.annotations.MyAutowired;
/**
* @author: Administrator
* @createTime: 2023/03/14 10:06
*/
public class Person {
private String name;
private Integer age;
public Person() {
System.out.println("默认构造器");
}
@MyAutowired
public Person(String name) {
System.out.println("@MyAutowired注解构造器");
this.name = name;
}
public Person(String name, Integer age) {
System.out.println("所有参数构造器");
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
自定义注解@MyAutowired
package com.gaogzhen.myspring.annotations;
import java.lang.annotation.*;
/**
* @author: Administrator
* @createTime: 2023/03/14 10:13
*/
@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
boolean required() default true;
}
MySmartInstantiationAwareBeanPostProcessor实现SmartInstantiationAwareBeanPostProcessor接口
package com.gaogzhen.myspring.processors;
import com.gaogzhen.myspring.annotations.MyAutowired;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import java.lang.reflect.Constructor;
import java.util.Arrays;
/**
* @author: Administrator
* @createTime: 2023/03/14 10:12
*/
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
if ("person".equalsIgnoreCase(beanClass.getSimpleName())) {
System.out.println(beanClass);
System.out.println("调用 MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 方法");
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
if (declaredConstructors != null) {
//获取有@MyAutowired注解的构造器列表
Constructor[] constructors = Arrays.stream(declaredConstructors).
filter(constructor -> constructor.isAnnotationPresent(MyAutowired.class))
.toArray(Constructor[]::new);
return constructors.length != 0 ? constructors : null;
}
}
return SmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass, beanName);
}
}
测试方法
@Test
public void testSmartInstantiationAwareBeanPostProcessor() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.addBeanPostProcessor(new MySmartInstantiationAwareBeanPostProcessor());
factory.registerBeanDefinition("name", BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("张三").getBeanDefinition());
factory.registerBeanDefinition("age", BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
.addConstructorArgValue(25).getBeanDefinition());
factory.registerBeanDefinition("person", BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.getBeanDefinition());
Person person = factory.getBean("person", Person.class);
System.out.println(person);
}
输出结果:
class com.gaogzhen.myspring.bean.Person
调用 MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 方法
2023-03-14 10:34:51 427 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'name'
2023-03-14 10:34:51 492 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'person' via constructor to bean named 'name'
@MyAutowired注解构造器
Person{name='张三', age=null}
- 实例化时,使用了@MyAutowired注解的构造器
bean实例化暂时讲解到这里,继续bean生命周期后续旅程。
后记
如果小伙伴什么问题或者指教,欢迎交流。
❓QQ:806797785
⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study
参考:
[1]Spring系列之Bean生命周期详解[CP/OL]