• Spring 框架Bean的初始化和销毁---方式:BeanPostProcessor后置处理器


    BeanPostProcessor后置处理器概述

    首先,我们来看下BeanPostProcessor的源码,看下它到底是个什么鬼,如下所示。

    package org.springframework.beans.factory.config;
    import org.springframework.beans.BeansException;
    import org.springframework.lang.Nullable;
    public interface BeanPostProcessor {
        @Nullable
        default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
        @Nullable
        default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    ​
    }

    从源码可以看出:BeanPostProcessor是一个接口,其中有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization两个方法,这两个方法分别是在spring容器中的bean初始化前后执行,所以spring容器中的每一个bean对象初始化前后,都会执行BeanPostProcessor接口的实现类的这两个方法。

    也就是说,postProcessBeforeInitialization方法会在bean实例化和属性设置之后,自定义初始化方法之前被调用,而postProcessAfterInitialization方法会在自定义初始化方法之后被调用。当容器中存在多个BeanPostProcessor的实现类时,会按照它们在容器中注册的顺序执行。对于自定义BeanPostProcessor实现类,还可以让其实现Ordered接口自定义排序。

    因此我们可以在每个bean对象初始化前后,加上自己的逻辑。实现方式:自定义一个BeanPostProcessor接口的实现类MyBeanPostProcessor,然后在类MyBeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法里面写上自己的逻辑。

    BeanPostProcessor后置处理器实例

    我们创建一个MyBeanPostProcessor类,实现BeanPostProcessor接口,如下所示。

    package io.mykit.spring.plugins.register.bean;
    ​
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    ​
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    ​
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("调用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean);
            return bean;
        }
    ​
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("调用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean);
            return bean;
        }
    }

    接下来,我们运行BeanLifeCircleTest类的testBeanLifeCircle04()方法,输出的结果信息如下所示。

    调用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192
    调用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192
    Cat类的构造方法...
    调用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab
    Cat的postConstruct()方法...
    Cat的init()方法...
    调用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab
    Cat的preDestroy()方法...
    Cat的destroy()方法...

    可以看到,postProcessBeforeInitialization方法会在bean实例化和属性设置之后,自定义初始化方法之前被调用,而postProcessAfterInitialization方法会在自定义初始化方法之后被调用。

    也可以让实现Ordered接口自定义排序,如下所示。

    package io.mykit.spring.plugins.register.bean;
    ​
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    ​
    /**
     * @author binghe
     * @version 1.0.0
     * @description 测试BeanPostProcessor
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
    ​
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("调用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean);
            return bean;
        }
    ​
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("调用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean);
            return bean;
        }
    ​
        @Override
        public int getOrder() {
            return 3;
        }
    }

    再次运行BeanLifeCircleTest类的testBeanLifeCircle04()方法,输出的结果信息如下所示。

    调用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a
    调用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a
    Cat类的构造方法...
    调用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32
    Cat的postConstruct()方法...
    Cat的init()方法...
    调用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32
    Cat的preDestroy()方法...
    Cat的destroy()方法...

    BeanPostProcessor后置处理器作用

    后置处理器用于bean对象初始化前后进行逻辑增强。spring提供了BeanPostProcessor的很多实现类,例如AutowiredAnnotationBeanPostProcessor用于@Autowired注解的实现,AnnotationAwareAspectJAutoProxyCreator用于SpringAOP的动态代理等等。

    除此之外,我们还可以自定义BeanPostProcessor的实现类,在其中写入需要的逻辑。下面以AnnotationAwareAspectJAutoProxyCreator为例,说明后置处理器是怎样工作的。我们都知道springAOP的实现原理是动态代理,最终放入容器的是代理类的对象,而不是bean本身的对象,那么spring是什么时候做到这一步的?就是在AnnotationAwareAspectJAutoProxyCreator后置处理器的postProcessAfterInitialization方法,即bean对象初始化完成之后,后置处理器会判断该bean是否注册了切面,如果是,则生成代理对象注入容器。Spring中的关键代码如下所示。

    /**
      * Create a proxy with the configured interceptors if the bean is
      * identified as one to proxy by the subclass.
      * @see #getAdvicesAndAdvisorsForBean
      */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
  • 相关阅读:
    MySQL事务的介绍+事务的特性+事务的开启
    MySQL误操作删除后,怎么恢复数据?
    笔记本如何开启WiFi热点?
    zabbix: Get value from agent failed: cannot connect to [[172.16.179.10]:10050]: [4] Interrupted system call
    考取RHCE认证的历程,总结的经验
    find的-xdev参数解释?
    keepalived+mysql主从环境,keepalived返回值是RST,需求解决方法?
    Centos 7 LVM xfs文件系统修复
    本文讲述下windows下使用rsync备份数据
    MySQL索引介绍+索引的存储类型+索引的优点和缺点+索引的分类+删除索引
  • 原文地址:https://www.cnblogs.com/cb1186512739/p/13284066.html
Copyright © 2020-2023  润新知