精华内容
下载资源
问答
  • 一、作用 ... 2.其里边的方法会在特定的时机被容器...大类分为容器级别的后置处理器以及Bean级别的后置处理器 1.BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor(容器级别的处理器) 2.BeanPostProcess

    一、作用

    1、本身也是一种需要注册到容器里的bean

    2.其里边的方法会在特定的时机被容器调用

    3.实现不改变容器或者Bean核心逻辑的情况下对Bean进行扩展

    4.对Bean进行包装,影响其行为、修改Bean的内容等

    二、PostProcessor的种类

    大类分为容器级别的后置处理器以及Bean级别的后置处理器

    1.BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor(容器级别的处理器)

    2.BeanPostProcessor(Bean级别的后置处理器,AOP思想的一种体现)

    展开全文
  • 现了spring后置处理器beanpostprocessor。为什么说beanpostprocessor重要的呢?我们先来看看 他的作用。 BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要...

    在这里插入图片描述

    	spring bean的生命周期完整过程一共有11步,但其中最重要的是第五步和第八步,因为它们先实
     现了spring后置处理器beanpostprocessor。为什么说beanpostprocessor重要的呢?我们先来看看
     他的作用。
    
    	BeanPostProcessor接口作用:
        如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定
     义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中,说白了就是 BeanPostProcessor类可
     以在【生成类的过程当中对我们的类产生代理】,并且对它里面的方法增强。
    

    我们来做一个案例 实际来操作一下
    1.创建一个带有增删改查的接口

    package com.zhou.ioc.demo3;
    
    public interface UserDao {
    
        public void  findAll();
    
        public void save();
    
        public void update();
    
        public void delete();
    }
    
    

    2.编写接口的实现类

    package com.zhou.ioc.demo3;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void findAll() {
            System.out.println("查询");
        }
    
        @Override
        public void save() {
            System.out.println("保存");
    
        }
    
        @Override
        public void update() {
            System.out.println("修改");
    
        }
    
        @Override
        public void delete() {
            System.out.println("删除");
    
        }
    }
    
    

    3.编写配置文件 applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <bean class="com.zhou.ioc.demo3.MyBeanPostProcessor"/>
    
        <bean id="userDao" class="com.zhou.ioc.demo3.UserDaoImpl"/>
    
    </beans>
    

    4.编写一个增加方法 的类 让其去 实现 beanpostprocessor 接口

    package com.zhou.ioc.demo3;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            //初始化Bean实例之前去执行方法
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            //剔除 beanName 不为 userDao
            if("userDao".equals(beanName)){
                //参数一:类加载器   参数二:用来指明生成哪个对象的代理对象,通过接口指定 参数三:用来指明产生的这个代理对象要做什么事情
                Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //如果方法是   save 就进行增强
                        if("save".equals(method.getName())){
                            System.out.println("权限校验======");
                            return method.invoke(bean,args);
                        }
                        return method.invoke(bean,args);
                    }
                });
                return proxy;
            }else {
                return bean;
            }
        }
    }
    
    

    5.接着编写测试类

    package com.zhou.ioc.demo3;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringDemo1 {
    
        @Test
        public void demo1(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) applicationContext.getBean("userDao");
    
            userDao.delete();
            userDao.findAll();
            userDao.save();
            userDao.update();
        }
    }
    
    

    6.测试结果

    删除
    查询
    权限校验======
    保存
    修改
    
    展开全文
  • Spring中有一个接口BeanPostProcessor,该接口我们叫后置处理器作用是在Bean对象实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。接口源码如下:一、自定义后置处理器/** * ...

    Spring中有一个接口BeanPostProcessor,该接口我们叫后置处理器,作用是在Bean对象实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。接口源码如下:

    715a7dd9f8be19e2d904aa1afc30dd88.png

    一、自定义后置处理器

    /** * BeanPostProcessor接口也叫后置处理器,作用是在Bean对象实例化和依赖注入完毕后, * 在显示调用初始化方法的前后添加我们自己的逻辑。 */@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {    /**     * 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务     * 注意:方法返回值不能为null     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中     * @param bean     * @param beanName     * @return     * @throws BeansException     */    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("初始化 before--实例化的bean对象:"+beanName);        // 可以根据beanName不同执行不同的处理操作        return bean;    }    /**     * 实例化、依赖注入、初始化完毕时执行     * 注意:方法返回值不能为null     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中     * @param bean     * @param beanName     * @return     * @throws BeansException     */    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("初始化 after...实例化的bean对象:"+beanName);        // 可以根据beanName不同执行不同的处理操作        return bean;    }}

    注:接口中两个方法不能返回null,如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象,因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

    然后定义实体类User:

    public class User {    private int id;    private String name;    public User(){        System.out.println("User 被实例化");    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        System.out.println("设置name="+name);        this.name = name;    }    public void customInit(){        System.out.println("User 中自定义的初始化方法");    }}

    再将User类配置成bean对象:

    @Bean(initMethod = "customInit") public User user(){        User user = new User();        user.setName("张三");        return user; }

    这里也可以使用xml配置。

    然后启动我们的项目,在控制台输出如下:

    User 被实例化

    设置name=张三

    初始化 before--实例化的bean对象:user

    User 中自定义的初始化方法

    初始化 after...实例化的bean对象:user

    通过输出语句我们能看到postProcessBeforeInitialization方法的输出语句是在Bean实例化及属性注入后执行的,且在自定义的初始化方法之前执行(通过Bean注解的initMethod指定)。而postProcessAfterInitialization方法是在自定义初始化方法执行之后执行的。

    注意:

    1.BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。

    2.BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法。

    ConfigurableBeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));factory.addBeanPostProcessor(new MyBeanPostProcessor());

    二、多个后置处理器

    我们可以在Spring中添加多个BeanPostProcessor(后置处理器)接口实现类,默认情况下Spring容器会根据后置处理器定义的顺序依次执行。

    当然,如果你想指定后置处理器的调用顺序,那么你可以通过实现Ordered接口的getOrder方法来自定义顺序。该方法默认值为 0,优先级最高,值越大优先级越低。

    @Componentpublic class MyBeanPostProcessor2 implements BeanPostProcessor, Ordered {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("第2个before--实例化的bean对象:"+beanName);        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("第2个after...实例化的bean对象:"+beanName);        return bean;    }    @Override    public int getOrder() {        return 2;    }}
    展开全文
  • 在前面几篇文章中梳理了Spring中bean的创建过程,...在这篇文章中,将按照出场顺序对后置处理器作用场景及发挥功能进行梳理。调用1 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()AbstractA...

    在前面几篇文章中梳理了Spring中bean的创建过程,在这个过程中各式各样的后置处理器发挥了不同的作用,可以说后置处理器贯穿了bean的实例化以及初始化过程。在这篇文章中,将按照出场顺序对后置处理器作用场景及发挥功能进行梳理。

    调用1

    InstantiationAwareBeanPostProcessor

    postProcessBeforeInstantiation()

     AbstractAutowireCapableBeanFactorycreateBean方法中调用,这时bean还没有被实例化:

    581644b46ce8bd9cc548481098e21cb4.png

    调用resolveBeforeInstantiation方法:

    6fd43fb22d848dce884788d32c625f84.png

    applyBeanPostProcessorsBeforeInstantiation方法:

    37f48c83a9a0885da5aea60fda7b192a.png

    在这里,首先拿到spring中提供的所有后置处理器,判断是不是InstantiationAwareBeanPostProcessor该后置处理器实现了BeanPostProcessor,在这调用了postProcessBeforeInstantiation方法。

    这里在目标对象被spring实例化之前调用,postProcessBeforeInstantiation方法的返回值类型是Object,可以返回任何类型的值。由于此时目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例,一般为代理对象。

    如果该方法的返回的Object对象代替了原本该生成的目标对象,那么就会把返回的对象放到单例池当中缓存,后续只有BeanPostProcessorpostProcessAfterInitialization方法会调用,其它方法不再调用。

    如果这里返回了null,就按照正常的流程创建对象,交给spring去负责对象的实例化。因此这个方法可以判断这个对象在spring实例化之前是否要做特殊的处理,比如不交给Spring管理,自己使用代理产生。

    调用2

    SmartInstantiationAwareBeanPostProcessor

    determineCandidateConstructors()

    AbstractAutowireCapableBeanFactorycreateBeanInstance方法中调用:

    90bc46364f77dd0f2fd0fd4c8adc815f.png

    determineConstructorsFromBeanPostProcessors方法,该方法用于推断实例化的构造方法,这里可能检测出bean拥有多个候选构造方法:

    96fccf6266a41b29f3be2874ffc63ccc.png

    SmartInstantiationAwareBeanPostProcessor接口的实现类AutowiredAnnotationBeanPostProcessor负责完成这个过程,如果有多个构造方法的情况下,ctors会返回空,后续使用默认无参构造方法进行实例化。但是如果有一个构造方法上有@Autowired注解,spring会优先选择这个方法。

    调用3

    MergedBeanDefinitionPostProcessor

    postProcessMergedBeanDefinition()

    AbstractAutowireCapableBeanFactorydoCreateBean 方法中调用:

    2e2bde126be51c7feae45f6e106915e2.png

    applyMergedBeanDefinitionPostProcessors方法:

    2661436ef824c5ab0ce90ece0c1a60e9.png

    在方法中对所有实现了MergedBeanDefinitionPostProcessor接口的后置处理器进行遍历,这里具体调用AutowiredAnnotationBeanPostProcessor,用于扫描需要注入的属性。

    AutowiredAnnotationBeanPostProcessor中,定义了两种需要扫描的注解类型,@Autowired@Value

    7032bad46f49a45f9a790a66ff279db3.png

    findAutowiredAnnotation方法中:

    7b264c2cf4c4f969c188143c48530abd.png

    对正在创建的bean进行扫描,如果有属性和方法上面加了这两个注解,就会把对应的方法或者属性保存,最终在buildAutowiringMetadata方法中封装成InjectionMetadata对象。

    0e6153856c9f8038f7ea1ff638f7b728.png

    需要注意这里的后置处理器仅仅用于扫描及缓存bean的注入信息,这里只完成了查找功能,没有完成属性的注入,属性的注入是在之后的另外的后置处理器中完成的。

    调用4

    SmartInstantiationAwareBeanPostProcessor

    getEarlyBeanReference()

    AbstractAutowireCapableBeanFactorydoCreateBean 方法中调用,主要用于处理Bean的循环依赖:

    3b1e6be6e233b717e2d6b28ae9122a7c.png

    在产生循环依赖后调用getEarlyBeanReference方法:

    d274235c08aa899db3a18a5c37666e83.png

    在这里遍历后置处理器,得到经过后置处理器代理后的对象,放入spring的二级缓存当中,提前暴露供循环引用的情况调用。注意这里返回的仅仅是一个对象,还算不上是一个完整的bean对象。这个具体调用过程在上一篇讲环依赖的中的文章讲的比较详细,如果有不明白的可以回顾一下。

    调用5

    InstantiationAwareBeanPostProcessor

    postProcessAfterInstantiation()

    AbstractAutowireCapableBeanFactorypopulateBean方法中调用:

    a9c1accba3ff9ec69cc43b9ac6a01772.png

    populateBean方法中

    5bf0425752aa437a9da9d56535092b70.png

    该方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null

    这里遍历后置处理器,如果实现了InstantiationAwareBeanPostProcessor,那么就调用postProcessAfterInstantiation方法。如果方法返回值为true,按照正常流程进行属性值的填充;如果该方法返回false,会忽略属性值的设置过程。简而言之,该后置处理器用于判断当前实例化完成的bean需不需要进行属性填充。

    调用6

    InstantiationAwareBeanPostProcessor

    postProcessPropertyValues()

    同样在populateBean方法中,在postProcessAfterInstantiation后返回true时执行,如果方法返回false,该方法不会被调用。

    dceea7ce4a6b8ce64cc21bbfeb0d11e9.png

    遍历后置处理器,如果属于InstantiationAwareBeanPostProcessor类型,则调用它的postProcessPropertyValues方法。

    这里发挥作用的是AutowiredAnnotationBeanPostProcessor,负责对添加了 @Autowired@Value等注解的属性进行依赖的填充。在其中遍历所有需要注入的属性的列表使用反射将注入的bean实例赋值给属性。(具体过程参照Spring实例化Bean源码解析)

    调用7

    BeanPostProcessor

    postProcessBeforeInitialization()

    AbstractAutowireCapableBeanFactorydoCreateBean方法中调用initializeBeanfan方法

    d6e271c88cb4324a03eb07ce5823bde3.png

    applyBeanPostProcessorsBeforeInitialization方法中:

    5f0563c5ec09674886cf74f53101f5e9.png

    在该方法中,遍历执行所有BeanPostProcessorpostProcessBeforeInitialization方法。

    d52296325c5d9113aa645c4e10aa7318.png

    在执行该方法前,bean已经被实例化完成,并且完成了属性的填充,因此这个过程属于后续的bean的初始化过程。

    需要注意的是,如果在bean中有方法被标注了@PostContrust注解,那么在CommonAnnotationBeanPostProcessor中,会调用该@PostContrust方法。

    调用8

    BeanPostProcessor

    postProcessAfterInitialization()

    和第7次调用入口相同,也是在AbstractAutowireCapableBeanFactory initializeBean方法中:

    40734154819bbdb49e9decf164431f3e.png

    applyBeanPostProcessorsAfterInitialization方法中:

    571320a7437d254fd5e50cb3f5f893e5.png

    遍历执行所有BeanPostProcessorpostProcessAfterInitialization方法。综上所述,bean的各种方法执行属性为,先执行构造方法,再执行后置管理器中的before方法及@PostContrust方法,最后执行后置处理器的after方法。

    调用9

    InitDestroyAnnotationBeanPostProcessor

    postProcessBeforeDestruction()

    如果当前bean中有方法被@PreDestroy注解标注,那么当Spring的ApplicationContext执行close方法时调用该后置处理器。在DefaultSingletonBeanRegistry中执行destroyBean方法:

    d2dd2d29770c3e7e35bed40a77f006a7.png

    调用destroy方法:

    304aa357e2d3717f07390953a0f3bb4e.png

    InitDestroyAnnotationBeanPostProcessorpostProcessBeforeDestruction方法:

    029fa4fdf057899a346bfb4446790dcd.png

    在该方法中,调用@PreDestroy注解标注的方法,执行销毁方法。

    总结

    本文对贯穿bean的实例化及初始化过程中出现的后置处理器进行了一下梳理,但是还有很多其他的后置处理器没有讲到。可以说后置处理器是spring提供给使用者的一些扩展点,如果能够熟练的使用这些后置处理器,能够帮助我们接触到一些spring中比较深层的东西,并对spring中的生命周期进行有利的插手。

    公众号后台回复

    "面试"---领取大厂面试资料

    "导图"---取24张Java后端学习笔记导图

    "架构"---取29本java架构师电子书籍

    "实战"---取springboot实战项目

    "视频"---取最新java架构师视频

    "加群"---加入学习交流群

    1c17027067818be0f8cb827172c7d468.png

    扫码关注公众号

    有趣、深入、直接

    与你聊聊java

    觉得有用,点个在看吧~
    展开全文
  • spring bean的后置处理器作用
  • BeanPostProcessor的作用是在调用初始化方法的前后添加一些逻辑,这里初始化方法是指在配置文件中配置init-method,或者实现了InitializingBean接口的afterPropertiesSet方法,注意不包括@PostConstruct这种初始化...
  • PropertyPlaceholderConfigurer 是 BeanFactory 后置处理器的实现,也是 BeanFactoryPostProcessor 接口的一个实现。允许将上下文(配置文件)中的属性值放在另一个单独的标准 JavaProperties 文件中去。在 XML 文件...
  • bean的后置处理器 : 对IOC容器中所有的bean都起作用. */ public class MyBeanPostProcessor implements BeanPostProcessor { /** 在bean的生命周期的初始化方法之前执行 Object bean: 正在被创建的bean对象. String...
  • BeanPostProcessor及其子类都实现了后置处理的功能。作用:在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下...
  • 一、BeanPostProcessor接口的作用 如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中去。 ...
  • spring有两种后置处理器: 1. 组件后置处理器——org.springframework.beans.factory.config.BeanPostProcessor; 2. 工厂后置处理器——org.springframework.beans.factory.config.BeanFactoryPostProcessor。 ...
  • Spring之BeanPostProcessor(后置处理器)介绍

    万次阅读 多人点赞 2019-03-03 13:10:33
      该接口我们也叫后置处理器作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化触发的。接口的源码如下 public interface BeanPostProcessor { .....
  • bean后置处理器作用:Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理。 1、创建bean后置处理器: 先创建一个类实现BeanPostProcessor接口,并具体提供: postProcessBeforeInitialization(Object...
  • 文章目录2.后置处理器2.1. BeanProcessor实现分析2.2 ApplicationContextAwareProcessor实现分析3.AOP3.1 使用案例3.2 源码分析核心类加载源码跟踪图 2.后置处理器 2.1. BeanProcessor实现...后置处理器作用:判...
  • 疑惑 @Configuraction注解的作用是什么,Spring是如何解析加了@Configuraction...ConfigurationClassPostProcessor 是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造。在这个类中,会解析加
  • 2.5、调用后置处理器

    2020-08-18 23:54:41
    在idea中搜索了一下Spring后置处理器(PostProcessor),找出了下图的几个 本文主要来分析红框中标出的两个,也就是在 refresh() 方法的第5步调用的后置处理器 1、后置处理器调用的时机 2、后置处理器调用的顺序 ...
  • AnnotationAwareAspectJAutoProxyCreator后置器的作用是什么? Spring AOP自动增强bean是如何实现的。 如何在spring上下文添加AnnotationAwareAspectJAutoProxyCreator? 如何利用ProxyFactory硬编码实现一个bean的...
  • 最近项目中使用了spring中的异步处理@EnableAsync和定时任务@EnableSchedule,二者作用在同一个service中,导致异步方法失效,最终发现还是不了解后置处理器作用导致的,还是图样图森破。 BeanPostProcessor 该接口...
  •   该接口我们也叫后置处理器作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下 public interface ...
  • InstantiationAwareBeanPostProcessor后置处理器,调用的是:postProcessBeforeInstantiation方法,第一次后置处理器作用是:给后置处理器一个返回代理对象的机会。这个方法用来在对象实例化前直接返回一个对象...
  • ConfigurationClassPostProcessor的作用是什么? @Configuration、@Component、@ComponentScan、@ComponentScans、@Bean、@Import等注解是如何完成bean注册的? @Conditional注解如何控制配置类是否需要解析? @...
  • BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。 ...
  • 总结(删除线部分为后置处理器部分)二.后置处理器1.什么时候起作用?2.如何处理?3.使用条件?三.实现代码1.Emp类2.Person类3.后置处理器类4.配置文件5.运行效果6.总结 一.生命周期 1.创建bean实例 public Emp() { ...
  • Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理,Bean后置处理器对IOC容器的所有bean实例逐一处理,而非单一实例。 我们可以定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IOC容器中...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 159
精华内容 63
关键字:

spring后置处理器作用

spring 订阅