spring中后置处理器

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

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

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


BeanFactory

Bean 工厂方面的后置处理器

  • BeanFactoryPostProcessor 获取IOC容器
  • BeanDefinitionRegistryPostProcessor 向容器注册Bean

1:BeanFactoryPostProcessor

Spring是一个bean依赖注入容器,容器是BF,它的上级对象是applicationContxt,applicationContxt在容器功能上附加了一下新的功能。我们使用spring时,用的都是applicationConext的实现类。
我们在初始化这些applicationConext时,最终调用的都是org.springframework.context.support.AbstractApplicationContext#refresh方法用于容器的初始化。这个方法是一个模板方法,规定了容器实例化的步骤。其中BF初始化完成后,会调用BF的后置处理器对BF进行后置处理。而后置处理器的调用是在org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors这个方法中进行的。
可以拿到Spring的IOC容器。ConfigurableListableBeanFactory

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

invokeBeanFactoryPostProcessors方法内,调用后置处理器的步骤如下:

  1. 通过ac(applicationContext)的addBeanFactoryPostProcessor方法加入的BD后置处理器,按照加入顺序调用。
  2. ac中类型为bd后置处理器的,拥有PriorityOrdered接口的BD后置处理器。
  3. ac中类型为bd后置处理器的,拥有Ordered接口的BD后置处理器。
  4. ac中类型为bd后置处理器的,PriorityOrdered和Ordered接口都没实现的BeanDefinitionRegistryPostProcessor
  5. ac中类型为bf后置处理器的,拥有PriorityOrdered接口的BF后置处理器。
  6. ac中类型为bf后置处理器的,拥有Ordered接口的BF后置处理器。
  7. ac中类型为bf后置处理器的,PriorityOrdered和Ordered接口都没实现的BeanFactoryPostProcessor

在AnnotationConfigApplicationContext上下文中,会有一个关键的BD后置处理器:ConfigurationClassPostProcessor。它是用来扫描所有交给spring管理的注解类的。将其解析为BD实例放到AC中去。

2:BeanDefinitionRegistryPostProcessor

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

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

例如:

Bean

Bean 方面的后置处理器BeanPostProcessor,这个bean后置处理器在spring的底层用的非常的多

spring管理的是bean,所以bean的实例化是一个重要的过程。spring是通过org.springframework.beans.factory.support.AbstractBeanFactory#getBean方法实例化并初始化Bean。实例化Bean的过程中,可以通过bean的后置处理器插手Bean的实例化过程。

Bean的实例化过程如下:

  1. 解析BD
  2. 确定构造方法
  3. 用构造方法实例化(构造方法依赖不能进行循环依赖)
  4. 属性注入
  5. 初始化

在这个过程中,spring内设了8个bean的后置处理器调用点,用来进行扩展。有5个后置处理器:

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,就必选要搞懂它提供的后置处理器功能。

 

本文转自:https://blog.csdn.net/u014297148/article/details/80412991/

https://blog.csdn.net/liuqi199707/article/details/111540443

https://www.jianshu.com/p/6e32426a2497?u_atoken=8df0b569-f21e-41aa-b7a0-1794a0c45adc&u_asession=01NJYXBbd02B2joDTXDBO4WF6E6xmbjrq_3bTLJoyj6dJNOGIk8d7HtXNpyyzBQ60hX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K88hgBKBWVVl9yMG4jTWLv5CvvWHyhA8I9G3hxoTho1LGBkFo3NEHBv0PZUm6pbxQU&u_asig=05PHkngCIBn4AI6DScvcchjiwnySJtQCKzFvojiVPdC7zb7vsBvJ_KO_D7vnh8ryrx8ozlX5syJtCNHMT6m_WE0G_S7BdbNlSN09n6J-zgnzzsfphKbJCNmjXA-h-UqR2NOoL2QZlpbxduKUE-3y2tnT70cDMDsjdDlLXoOFhWM_b9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzXS0idHrqpG2hDzDUwiEDG7-fKe0TvwVN4YTWQicPVaAChTz2MQxpCmDDGYlh3aZze3h9VXwMyh6PgyDIVSG1W88GDEzy7ZTJgWZe8pE5RdS7JPH1ToEoKDgsCNHHWCJPMVIGIuy3FU8GChSfyfUMWPcmeGRJXY26SLI-WXupu0AmWspDxyAEEo4kbsryBKb9Q&u_aref=U81RQlPfNZ%2FTEmX25m%2Bm79CqkHQ%3D

 

 

posted @ 2022-08-26 23:06  ppjj  阅读(1701)  评论(0编辑  收藏  举报