Spring后置处理器BeanPostProcessor源码解析

引言

如果对BeanPostProcessor的使用不是很了解的,可以参考另一篇文章:

https://blog.csdn.net/zxd1435513775/article/details/83019572

BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中会回调BeanPostProcessor中定义的两个方法。BeanPostProcessor源码如下:

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

具体在什么时候调用这两个方法呢?

postProcessBeforeInitialization方法会在每一个bean对象的初始化方法调用之前回调
postProcessAfterInitialization方法会在每个bean对象的初始化方法调用之后被回调

自定义BeanPostProcessor

由上面BeanPostProcessor源码可以看到它两个方法的参数都相同,其中:

  • 第一个参数Object bean表示当前正在初始化的bean对象

  • 两个方法都返回Object类型的实例,返回值既可以是将入参Object bean原封不动的返回出去,也可以对当前bean进行包装再返回

来看看下面的自定义BeanPostProcessor

// 后置处理器:在每一个bean初始化前后进行处理工作,需要将后置处理器加入到容器中
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean);
        return bean;
    }
}

Spring容器中加入MyBeanPostProcessor之后,针对容器中每个创建的Bean对象,既包括Spring自身创建的Bean,也包括应用程序创建的Bean,都会回调postProcessBeforeInitializationpostProcessAfterInitialization方法。

执行原理

BeanPostProcessor的执行是在容器的刷新过程中,容器刷新对象具体的方法为:

AbstractApplicationContext.refresh()

在refresh方法执行的调用栈中会去调用AbstractAutowireCapableBeanFactory.doCreateBean()方法,该方法节选源码如下

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				invokeAwareMethods(beanName, bean);
				return null;
			}
		}, getAccessControlContext());
	}else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
        // 调用postProcessBeforeInitialization方法
		wrappedBean = applybeanpostprocessorsbeforeinitialization(wrappedbean, beanname);
	}

	try {
        // 调用初始化方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}

	if (mbd == null || !mbd.isSynthetic()) {
        // 调用postProcessAfterInitialization方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitialization()applyBeanPostProcessorsAfterInitialization()

applyBeanPostProcessorsBeforeInitialization()方法的源码如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

	Object result = existingBean;
	// 会拿到所有的BeanPostProcessor,进行逐一遍历
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}


public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

	Object result = existingBean;
    // 会拿到所有的BeanPostProcessor,进行逐一遍历
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}

可以看到其逻辑为:

遍历得到容器中所有的BeanPostProcessor,然后执行postProcessBeforeInitialization,一但返回null,就跳出for循环,不执行后面的BeanPostProcessor.postProcessorsBeforeInitialization()

也就是说,如果返回的是null,那么我们通过getBean方法将得不到目标Bean。

applyBeanPostProcessorsAfterInitialization()方法的逻辑和上面一致,Spring底层的很多功能特性都是借助BeanPostProcessor的子类来实现。

BeanPostProcessor的继承结构如下:
这里写图片描述

常见BeanPostProcessor分析

下图是debug过程中,ApplicationContext对象中的包含的BeanPostProcessor。具体包含哪些BeanPostProcessor与具体应用程序相关,除了下标3中的MyBeanPostProcessor为自定义的BeanPostProcessor,其余均为Spring自带的BeanPostProcessor
这里写图片描述
下面来分析一下ApplicationContextAwareProcessorAutowiredAnnotationProcessor的执行原理。

ApplicationContextAwareProcessor

ApplicationContextAwareProcessor后置处理器的作用是:当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象

@Component
public class Car implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Car(){
        System.out.println("car instance...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware...setApplicationContext()");
        this.applicationContext = applicationContext;
    }
}

那Car是如何通过实现ApplicationContextAware接口就能获得ApplicationContext对象呢?

答案:通过ApplicationContextAwareProcessor后置处理器来实现,下面来看看ApplicationContextAwareProcessor的源码

// 实现BeanPostProcessor接口
class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;

    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }

    // 实现BeanPostProcessor接口中的postProcessBeforeInitialization
    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        
        AccessControlContext acc = null;
        // 这里bean是Car,它实现了ApplicationContextAware接口
        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            
            // 如果实现了ApplicationContextAware接口,就是执行下面方法
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    // 这里bean是Car
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            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) {
                // 会执行这里回调car重写的setApplicationContext方法,然后将this.applicationContext注入给Car
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    // 实现BeanPostProcessor接口中的postProcessAfterInitialization
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

InitDestroyAnnotationBeanPostProcessor

InitDestroyAnnotationBeanPostProcessor后置处理器是用来处理自定义的初始化方法和销毁方法

Spring中提供了3种自定义初始化和销毁方法:

  • 通过@Bean注解指定init-methoddestroy-method属性

  • Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)两个接口

  • @PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法@PreDestroy,在容器销毁bean之前通知我们进行清理工作

InitDestroyAnnotationBeanPostProcessor的作用就是让第3种方式生效

先看看如何使用@PostConstruct@PreDestroy注解。

@Component
public class Car {

    public Car(){
        System.out.println("car instance...");
    }

    // 自定义的初始化方法
    @PostConstruct
    public void init(){
        System.out.println("car ... init...");
    }

    // 自定义的销毁方法
    @PreDestroy
    public void detory(){
        System.out.println("car ... detory...");
    }
}

InitDestroyAnnotationBeanPostProcessor在Bean创建的时候通过反射的方式查找包含@PostConstruct@PreDestroy注解的方法,然后再通过反射执行方法。

我们来看看InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()的源码

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    // 获取bean的metadata
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   
    try {
        // 执行@PostConstruct指定的init方法
        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;
}

metadata中已经解析出initMethodsdestroyMethods,其具体内容如下

这里写图片描述

metadata.invokeInitMethods(bean, beanName)

这个方法调用就是根据反射执行init方法

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor也是个接口,它是BeanPostProcessor的子接口

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    //实例化Bean之前调用
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    //实例化Bean之后调用
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    //设置Bean对象中的某个属性时调用
    PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

这两个接口的功能基本类似,不过要注意InstantiationAwareBeanPostProcessorBeanPostProcessor的方法名区别

InstantiationAwareBeanPostProcessor中是InstantiationBeanPostProcessorInitialization

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

止步前行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值