• 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

  • 相关阅读:
    [NOIP模拟赛][贪心]奶牛晒衣服.
    BZOJ3750: [POI2015]Piecz
    BZOJ2348 [Baltic 2011]Plagiarism
    高精度乘法【高乘高
    codevs 1215 迷宫
    变量交换
    a+b问题与圆柱体表面积的计算
    算数表达式的练习
    [bzoj1070][SCOI2007]修车[ 网络流]
    [bzoj2502]清理雪道[上下界网络流]
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/16629531.html
Copyright © 2020-2023  润新知