Spring后置处理器(BeanPostProcessor)(BeanFactoryPostProcessor)

  • Post author:
  • Post category:其他



Spring的后置处理器,在应用Spring框架开发中非常重要,Spring底层的核心,就通过各种后置处理器去完成IOC容器的启动,AOP代理对象的创建。


Spring的后置处理器有两大类,

BeanFactory



Bean





BeanFactory

Bean 工厂方面的后置处理器



  • BeanFactoryPostProcessor

    获取IOC容器


  • BeanDefinitionRegistryPostProcessor

    向容器注册Bean


1:

BeanFactoryPostProcessor



可以拿到Spring的IOC容器。ConfigurableListableBeanFactory

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;


2:

BeanDefinitionRegistryPostProcessor



BeanDefinitionRegistry Spring注册Bean的工具类,可以向容器手动注册Bean。

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

例如:

在这里插入图片描述





Bean

Bean 方面的后置处理器



  • SmartInstantiationAwareBeanPostProcessor

    设置Bean的类型,构造函数


  • InstantiationAwareBeanPostProcessor

    Bean实例化之前,属性赋值之前的处理器


  • MergedBeanDefinitionPostProcessor

    再添加或修改Bean的定义信息


  • BeanPostProcessor

    Bean初始化之后的处理器,所有后置处理器的顶级接口。可以修改Bean实例的信息,甚至修改Bean的引用指向。


1:

SmartInstantiationAwareBeanPostProcessor



设置Bean的类型,构造函数。

基于Spring开发框架使用,平时开发不要使用。

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    /**
     * 设置 Bean 的类型
     */
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    /**
     * 设置创建 Bean用到的 构造函数
     */
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {

        return null;
    }
    /**
     * 循环引用从此处获取 Bean实例
     */
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

假如在创建一个

UserService.class

的Bean,如下我指定成

EmployeeService.class

,构造函数也是

EmployeeService

的无参构造函数,那么创建

UserService Bean

实例就会变成

EmployeeService

的实例。

default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("userService")) {
            return EmployeeService.class;
        }
        return null;
    }
    /**
     * 设置创建 Bean用到的 构造函数
     */
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {
        if (beanName.equals("userService")) {
            try {
                return new Constructor[]{EmployeeService.class.getConstructor()};
            } catch (Exception e) {
            }
        }
        return null;
    }


2:

InstantiationAwareBeanPostProcessor




postProcessBeforeInstantiation

:Bean实例化之前执行此方法,如果返回不为

null

,则替代当前准备实例化的Bean,Spring将不再自动实例化对象了。


postProcessAfterInstantiation

:如果返回 true,执行

postProcessProperties

方法。


postProcessProperties

:设置实例化Bean需要的属性,调用 set 方法赋值,如果指定的属性名没有set方法,则报错。

/**
     * 在Spring实例化Bean之前调用,该方法如果返回结果不为空,
     * 这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。
     * 如果该方法的返回值代替原本该生成的目标对象,
     * 后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
     *
     * @param beanClass     Spring当前正在创建的Bean的类型
     * @param beanName      Spring当前正在创建的Bean的name
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * 在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。
     *
     * 如果返回 true 调用 postProcessProperties设置属性值,然后 set 方法赋值
     * @return
     * @throws BeansException
     */
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")) {
            return true;
        }
        return false;
    }
    /**
     * 设置属性值  为 Bean的 set 方法赋值
     *
     * 例如 添加了一个属性 password,会调用 bean的 setPassword方法,如果该方法没有,会报错
     */
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")) {
            ( (MutablePropertyValues) pvs).addPropertyValue(new PropertyValue("password", "123"));
            return pvs;
        }
        return null;
    }


3:

MergedBeanDefinitionPostProcessor

再添加或修改Bean的定义信息

/**
     * @param beanDefinition 当前正在创建Bean的定义信息,可以用它再添加或修改一些定义信息
     *                       beanDefinition.setLazyInit(true); 设置懒加载为 true
     */
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

    /**
     * 如果修改了当前正在创建的Bean的 name 会执行
     * @param beanName
     */
    default void resetBeanDefinition(String beanName) {
    }


4:

BeanPostProcessor




postProcessBeforeInitialization

Bean初始化方法之前执行,可以返回一个对象,替代Spring当前的Bean实例。


postProcessAfterInitialization

Bean初始化最后的一个处理方法,可以返回一个对象,替代Spring当前的Bean实例。

AOP代理在此创建

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}



Spring底层源码的总结:

看过Spring源码的,就会知道Spring的启动流程,只是提供了一个注册特定的组件(后置处理器),及实例化Bean的模板功能。其他功能:依赖注入,AOP切面,事务管理,异步执行…等等一系列的拓展功能,都是在后置处理器中执行。所以要学好Spring,就必选要搞懂它提供的后置处理器功能。

在这里插入图片描述



版权声明:本文为liuqi199707原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。