共计 11543 个字符,预计需要花费 29 分钟才能阅读完成。
InstantiationAwareBeanPostProcessor 接口继承了 BeanPostProcessor 接口。
BeanPostProcessor 次要是在 Bean 调用初始化办法前后进行拦挡。
而 InstantiationAwareBeanPostProcessor 接口在 BeanPostProcessor 根底上增加了对 bean 的创立前后,以及设置属性前进行拦挡。
它的办法如下:
办法 | 执行程序 | 备注 |
---|---|---|
postProcessBeforeInstantiation() | 在 Bean 创立前调用 | 可用于创立代理类,如果返回的不是 null(也就是返回的是一个代理类),那么后续只会调用 postProcessAfterInitialization() 办法 |
postProcessAfterInstantiation() | 在 Bean 创立后调用 | 返回值会影响 postProcessProperties() 是否执行,其中返回 false 的话,是不会执行。 |
postProcessProperties() | 在 Bean 设置属性前调用 | 用于批改 bean 的属性,如果返回值不为空,那么会更改指定字段的值 |
postProcessBeforeInitialization() | 在 Bean 调用初始化办法前调用 | 容许去批改 bean 实例化后,没有调用初始化办法前状态的属性 |
postProcessAfterInitialization() | 在 Bean 调用初始化办法后调用 | 容许去批改 bean 调用初始化办法后状态的属性 |
验证
TestBean 类
public class TestBean implements InitializingBean {
protected Object field;
public TestBean() {System.out.println("创立 TestBean 对象");
}
public Object getField() {return field;}
public void setField(Object field) {System.out.println("设置 field 属性");
this.field = field;
}
@Override
public void afterPropertiesSet() throws Exception {System.out.println("调用初始化办法");
}
@Override
public String toString() {
return "TestBean{" +
"field=" + field +
'}';
}
}
InstantiationAwareBeanPostProcessor 类
/**
* InstantiationAwareBeanPostProcessor 的实现类
*/
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if(isMatchClass(beanClass)){System.out.println("调用 postProcessBeforeInstantiation 办法");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if(isMatchClass(bean.getClass())){System.out.println("调用 postProcessAfterInstantiation 办法");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if(isMatchClass(bean.getClass())){System.out.println("调用 postProcessProperties 办法");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if(isMatchClass(bean.getClass())){System.out.println("调用 postProcessBeforeInitialization 办法");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if(isMatchClass(bean.getClass())){System.out.println("调用 postProcessAfterInitialization 办法");
}
return bean;
}
private boolean isMatchClass(Class<?> beanClass){
// ClassUtils 类为 org.springframework.util.ClassUtils
return TestBean.class.equals(ClassUtils.getUserClass(beanClass));
}
}
测试类
@SpringBootTest
public class CustomProcessorTest {
@Autowired
private ApplicationContext applicationContext;
@Test
void test(){TestBean testBean = applicationContext.getBean(TestBean.class);
System.out.println(testBean);
}
/**
* 创立 TestBean 和 CustomInstantiationAwareBeanPostProcessor 这 2 个 bean
*/
@TestConfiguration
static class TestConfig{
@Bean
public TestBean getTestBean(){TestBean testBean = new TestBean();
testBean.setField("1");
return testBean;
}
@Bean
public CustomInstantiationAwareBeanPostProcessor customInstantiationAwareBeanPostProcessor(){return new CustomInstantiationAwareBeanPostProcessor();
}
}
}
执行后果
调用 postProcessBeforeInstantiation 办法
创立 TestBean 对象
设置 field 属性
调用 postProcessAfterInstantiation 办法
调用 postProcessProperties 办法
调用 postProcessBeforeInitialization 办法
调用初始化办法
调用 postProcessAfterInitialization 办法
TestBean{field=1}
分析方法
1. postProcessBeforeInstantiation()
postProcessBeforeInstantiation() 办法是在 Bean 创立之前调用的,该办法容许咱们返回 Bean 的其余子类(咱们也能够用 cglib 返回一个代理对象)。
这个办法在 InstantiationAwareBeanPostProcessor 接口的默认实现是返回 null。
论断
如果 postProcessBeforeInstantiation() 返回的不是 null,那么 Spring 只会在 Bean 创立的时候,
只调用 postProcessBeforeInstantiation() 和 postProcessAfterInitialization() 办法。
验证
批改 CustomInstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation() 办法:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (isMatchClass(beanClass)) {System.out.println("调用 postProcessBeforeInstantiation 办法");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanClass);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {System.out.println("指标办法执行前:" + method);
Object object = proxy.invokeSuper(obj, args);
System.out.println("指标办法执行后:" + method);
return object;
});
return enhancer.create();}
return null;
}
执行后果:
调用 postProcessBeforeInstantiation 办法
创立 TestBean 对象
调用 postProcessAfterInitialization 办法
指标办法执行前:public java.lang.String TestBean.toString()
指标办法执行后:public java.lang.String TestBean.toString()
TestBean{field=null}
从执行后果中看,Spring 容器只执行了 postProcessBeforeInstantiation() 和 postProcessAfterInitialization() 办法,CustomInstantiationAwareBeanPostProcessor 其余的办法均不执行。
也没有执行 TestBean 的 setField() 和 afterPropertiesSet() 办法。
起因
从 Spring 创立 Bean 的过程中动手, Spring 在创立 Bean 时,会调用 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);
if (bean != null) {return bean;}
}
catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean'" + beanName + "'");
}
return beanInstance;
}
// 省略上面的办法
}
从 createBean() 的代码片段中,它先去调用 resolveBeforeInstantiation() 办法来尝试获取代理类,如果获取到了,就间接返回该代理类。
否则就去调用 doCreateBean() 办法,以创立 bean 的实例,并且返回。
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;
}
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里会遍历每一个 InstantiationAwareBeanPostProcessor 的子类,所以 InstantiationAwareBeanPostProcessor 的子类程序很重要
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
// 如果返回的不为 null,前面的所有 InstantiationAwareBeanPostProcessor 的子类就跳过执行了
if (result != null) {return result;}
}
return null;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 这里会遍历每一个 BeanPostProcessor 的子类,所以 BeanPostProcessor 的子类程序很重要
Object current = processor.postProcessAfterInitialization(result, beanName);
// 如果返回的为 null,前面的所有 BeanPostProcessor 的子类就跳过执行了
if (current == null) {return result;}
result = current;
}
return result;
}
从 resolveBeforeInstantiation() 办法的代码片段中,它的逻辑根本是这样:
- 遍历所有的 InstantiationAwareBeanPostProcessor 实现类,调用其 postProcessBeforeInstantiation() 办法。
- 如果 postProcessBeforeInstantiation() 办法返回值,那么就示意找到了代理类,那么就会完结遍历
- 如果步骤 2 没有找到代理类,那么 resolveBeforeInstantiation() 办法就根本执行完结,返回 null 值。
- 如果步骤 2 找到了代理类,就会遍历所有 BeanPostProcessor 的实现类,调用其 postProcessAfterInitialization() 办法。
- 如果 postProcessAfterInitialization() 办法返回的是 null,那么就返回上一次遍历失去的后果,或者是代理类自身。
2. postProcessAfterInstantiation()
postProcessAfterInstantiation() 办法的返回值会影响 postProcessProperties() 是否会执行:
- false:不会执行
- true:执行
起因
下面曾经提及了 Spring 创立 Bean 是会调用 createBean() 办法,其中如果 postProcessBeforeInstantiation() 返回的值为 null 的话,就会执行 doCreateBean() 办法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 疏忽下面代码
Object exposedObject = bean;
try {populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 疏忽上面代码
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 疏忽下面代码
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {// 遍历所有 InstantiationAwareBeanPostProcessor,并调用其 postProcessAfterInstantiation() 办法,如果返回 false,就不会执行后续步骤了。if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}
}
}
// 疏忽两头局部代码
if (hasInstantiationAwareBeanPostProcessors()) {if (pvs == null) {pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {// 遍历所有 InstantiationAwareBeanPostProcessor,并调用其 postProcessProperties() 办法,如果存在返回的值为 null,就不会执行后续步骤了
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {return;}
pvs = pvsToUse;
}
}
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {// 依据调用所有 InstantiationAwareBeanPostProcessor 的 postProcessProperties() 办法所失去的值,来批改这个 bean 的属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
从下面的代码片段中,doCreateBean() 办法会调用 populateBean() 办法,其中 populateBean() 办法它的次要逻辑是:
- 遍历所有 InstantiationAwareBeanPostProcessor,调用 postProcessAfterInstantiation() 办法,如果返回值为 false 了,就不会执行后续步骤了
- 遍历所有 InstantiationAwareBeanPostProcessor,调用 postProcessProperties() 办法,如果返回值为 null,就不会执行后续的其余步骤了
- 如果 pvs 的值不为空,那么就去调用 applyPropertyValues() 办法来设置 bean 的属性
3. postProcessProperties()
postProcessProperties() 办法返回的 PropertyValues 会影响 bean 属性的设置。
论断
如果 PropertyValues 为 null,PropertyValues 外面没有数据,就不会对 bean 的属性做任何批改。
否则,就会批改 Bean 的属性值。
验证
批改 CustomInstantiationAwareBeanPostProcessor 类的 postProcessProperties() 办法逻辑:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if (isMatchClass(bean.getClass())) {System.out.println("调用 postProcessProperties 办法");
MutablePropertyValues mpvs = (MutablePropertyValues) pvs;
// 这里批改 TestBean 的 field 字段值为 "update value"
mpvs.add("field","update value");
}
return pvs;
}
输入后果:
调用 postProcessBeforeInstantiation 办法
创立 TestBean 对象
设置 field 属性
调用 postProcessAfterInstantiation 办法
调用 postProcessProperties 办法
设置 field 属性
调用 postProcessBeforeInitialization 办法
调用初始化办法
调用 postProcessAfterInitialization 办法
TestBean{field=update value}
4. postProcessBeforeInitialization() 和 postProcessAfterInitialization()
postProcessBeforeInitialization() 和 postProcessAfterInitialization() 这 2 个办法是在 Bean 的属性设置完之后执行的,能够通过这 2 个办法来实现对 Bean 的属性进行批改。
当 Spring 在 AbstractAutowireCapableBeanFactory 的 doCreateBean() 办法中调用完了 populateBean() 的办法后,就会调用 initializeBean() 办法。
故 initializeBean() 办法是 Spring 调用 postProcessBeforeInitialization() 和 postProcessAfterInitialization() 的次要逻辑:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {// 遍历所有 BeanPostProcessor 的子类,并调用 postProcessBeforeInitialization() 的办法
// 如果 postProcessBeforeInitialization() 返回 null,则返回上一个 BeanPostProcessor 子类返回的对象,// 或者是 bean 对象自身(如果调用第一个 BeanPostProcessor 子类就返回 null 的话)wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {// 调用 bean 指定的 init 办法,或者是实现 InitializingBean 的 afterPropertiesSet() 办法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
}
if (mbd == null || !mbd.isSynthetic()) {// 遍历所有 BeanPostProcessor 的子类,并调用 postProcessAfterInitialization() 的办法
// 如果 postProcessAfterInitialization() 返回 null,则返回上一个 BeanPostProcessor 子类返回的对象,// 或者是 bean 对象自身(如果调用第一个 BeanPostProcessor 子类就返回 null 的话)wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
参考博客 / 论坛
- Spring Boot –如何初始化 Bean 进行测试
- Spring 之 InstantiationAwareBeanPostProcessor 接口介绍
- How to get a bean real class instead CGlib proxy?