Spring之Bean后处理器——InstantiationAwareBeanPostProcessor的使用与源码解析

Spring之Bean后处理器——InstantiationAwareBeanPostProcessor的使用与源码解析,第1张

文章目录
      • InstantiationAwareBeanPostProcessor介绍
        • InstantiationAwareBeanPostProcessor执行流程
      • InstantiationAwareBeanPostProcessor使用
        • Book
        • Pen
        • BookProxyInstantiationAwareBeanPostProcessor
        • main
        • 全量代码
        • 执行结果
      • 源码解析
      • 总结

InstantiationAwareBeanPostProcessor介绍

InstantiationAwareBeanPostProcessor接口扩展了BeanPostProcessor子接口,提供了Bean被实例化之前、Bean实例化之后、Bean属性装配前更细粒度控制Bean创建流程的处理。

由于InstantiationAwareBeanPostProcessor扩展了BeanPostProcessor接口,所以该篇文章部分内容会与BeanPostProcessor接口的流程重合;尽管如此,也建议在看该篇文章前,先阅读关于BeanPostProcessor接口的详细介绍与源码解析:Spring之Bean后处理器——BeanPostProcessor的使用与源码解析

InstantiationAwareBeanPostProcessor接口比BeanPostProcessor新增了如下方法:

方法描述
Object postProcessBeforeInstantiation(Class beanClass, String beanName)Bean实例化之前,调用此方法;该方法传入目标Bean类型与BeanName;该方法可以返回一个该Bean类型的对象,或对该Bean的一个代理对象;当该方法返回了实例化对象后,后续的所有Bean实例化与初始化的动作将不再进行。只会调用后续的BeanPostProcessor#postProcessAfterInitialization()方法。
boolean postProcessAfterInstantiation(Object bean, String beanName)Bean实例化之后,调用此方法;该方法传入还没有装配属性的Bean对象以及BeanName。 如果该方法返回true,则将跳过后续的属性装配动作,一般应该返回true
PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)Bean实例化之后,装配属性之前,调用此方法;该方法传入在配置期间所配的PropertyValues以及BeanName。 该方法返回的PropertyValues将最终装配到Bean对象中。
InstantiationAwareBeanPostProcessor执行流程


InstantiationAwareBeanPostProcessor流程如下:

  • 执行Bean实例化之前,执行postProcessBeforeInstantiation();
  • 执行Bean实例化之后执行postProcessAfterInstantiation();
  • 执行Bean属性装配前执行postProcessProperties();
  • Bean属性装配后执行postProcessBeforeInitialization();
  • Bean的Init相关初始化完毕后执行postProcessAfterInitialization();

下图能比较好的反应出过程:

InstantiationAwareBeanPostProcessor使用

接下来写个例子。全量代码会在最后贴出来,直接CV运行即可。

Book

Book类,它实现了InitializingBean接口,其afterPropertiesSet()方法仅输出一行信息用来记录执行流程;还有一个customInit()方法使其加入到Springinit-method的执行过程;该类还有一个show()方法,用来在后面的BookProxyInstantiationAwareBeanPostProcessor处理器中对原始的Book对象生成一个代理类,该代理类将对show()方法进行增强处理,用来让咱们的BeanPostProcessor能实际干点事儿。
但是由于BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()返回了代理对象,所以后续Book后续的初始化都不会在进行,所以其afterPropertiesSet()customInit()方法也不会再调用。

public class Book implements InitializingBean {
    private String name;
    private String author;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public void show() {
        System.out.printf("book#show():%s\n", this);
    }

    public void customInit() {
        System.out.printf("%-85s:%s{%s}%n", "------Book#customInit", this.getClass().getSimpleName(), this);
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.printf("%-85s:%s{%s}%n", "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
    }
}
Pen

Pen类与Book类一样,它实现了InitializingBean接口,其afterPropertiesSet()方法仅输出一行信息用来记录执行流程;还有一个customInit()方法使其加入到Springinit-method的执行过程;

public class Pen implements InitializingBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pen{" +
                "name='" + name + '\'' +
                '}';
    }

    public void customInit() {
        System.out.printf("%-85s:%s{%s}%n", "------Pen#customInit", this.getClass().getSimpleName(), this);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.printf("%-85s:%s{%s}%n", "------Pen#afterPropertiesSet", this.getClass().getSimpleName(), this);
    }
}
BookProxyInstantiationAwareBeanPostProcessor

BookProxyInstantiationAwareBeanPostProcessor实现了InstantiationAwareBeanPostProcessor接口;在其postProcessBeforeInstantiation()方法中对Book类型进行判断,如果是Book类型则使用CGLIB生成其代理,用来增强Book#show()方法,在其前后各打印一句话。其余方法都仅输出一条信息,用来描述其执行过程。

public class BookProxyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.printf("%-85s:%s%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
        //判断传入的beanClass是否是Book类型
        if (Book.class.equals(beanClass)) {
            System.out.printf("3[1;33m%-85s:对[%s]的3[1;31mshow()3[1;33m方法进行增强 3[0m%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
            //创建Book类的代理
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Book.class);
            enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
                //如果不是show()方法则直接调用返回
                if (!method.equals(Book.class.getMethod("show"))) {
                    return methodProxy.invokeSuper(obj, args);
                }
                //对show()做增强处理
                System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行前");
                Object result = methodProxy.invokeSuper(obj, args);
                System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行后");
                return result;
            });
            Book book = (Book) enhancer.create();
            book.setName("《非暴力沟通》");
            book.setAuthor("马歇尔·卢森堡");
            return book;
        }

        return null;
    }
    
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation", bean.getClass().getSimpleName(), bean);
        return true;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInitialization", bean.getClass().getSimpleName(), bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInitialization", bean.getClass().getSimpleName(), bean);
        return bean;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessProperties", bean.getClass().getSimpleName(), bean);
        pvs.forEach((name) -> {
            System.out.printf("%85s:%s {%s=%s}%n", "pvs", bean.getClass().getSimpleName(), name.getName(), name.getValue());
        });

        return pvs;
    }
}
main

定义一个Book类型与Pen类型的GenericBeanDefinition,将BookPencustomInit()添加到BeanDefinition中,并设置PenMutablePropertyValues用于初始化后的属性装配。
同时将BookProxyInstantiationAwareBeanPostProcessor注册到容器中。

public static void main(String[] args) {
    GenericApplicationContext context = new GenericApplicationContext();
    //注册Book的BeanDefinition
    GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
    bookBeanDefinition.setBeanClass(Book.class);
    bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
    bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
    context.registerBeanDefinition("book", bookBeanDefinition);
    //注册Pen的BeanDefinition
    GenericBeanDefinition penBeanDefinition = new GenericBeanDefinition();
    penBeanDefinition.setBeanClass(Pen.class);
    penBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
    penBeanDefinition.setInitMethodName("customInit");//设置初始化方法
    //设置pen属性
    penBeanDefinition.setPropertyValues(new MutablePropertyValues()
            .addPropertyValue(new PropertyValue("name", "英雄钢笔"))
    );
    context.registerBeanDefinition("pen", penBeanDefinition);//注册BeanDefinition
    //注册BookProxyInstantiationAwareBeanPostProcessor后处理器
    context.registerBean(BookProxyInstantiationAwareBeanPostProcessor.class);
    //刷新容器
    context.refresh();
    //获取Book的bean对象,调用show()方法
    context.getBean("book", Book.class).show();
}
全量代码

package com.baiyang.beanpostprocessor.instantiationaware;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.context.support.GenericApplicationContext;

import java.util.concurrent.atomic.AtomicInteger;

public class BookProxyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    public static AtomicInteger COUNT = new AtomicInteger();

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.printf("%-85s:%s%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
        //判断传入的beanClass是否是Book类型
        if (Book.class.equals(beanClass)) {
            System.out.printf("3[1;33m%-85s:对[%s]的3[1;31mshow()3[1;33m方法进行增强 3[0m%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
            //创建Book类的代理
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Book.class);
            enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
                //如果不是show()方法则直接调用返回
                if (!method.equals(Book.class.getMethod("show"))) {
                    return methodProxy.invokeSuper(obj, args);
                }
                //对show()做增强处理
                System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行前");
                Object result = methodProxy.invokeSuper(obj, args);
                System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行后");
                return result;
            });
            Book book = (Book) enhancer.create();
            book.setName("《非暴力沟通》");
            book.setAuthor("马歇尔·卢森堡");
            return book;
        }

        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation", bean.getClass().getSimpleName(), bean);
        return true;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInitialization", bean.getClass().getSimpleName(), bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInitialization", bean.getClass().getSimpleName(), bean);
        return bean;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessProperties", bean.getClass().getSimpleName(), bean);
        pvs.forEach((name) -> {
            System.out.printf("%85s:%s {%s=%s}%n", "pvs", bean.getClass().getSimpleName(), name.getName(), name.getValue());
        });

        return pvs;
    }


    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        //注册Book的BeanDefinition
        GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
        bookBeanDefinition.setBeanClass(Book.class);
        bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
        bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
        context.registerBeanDefinition("book", bookBeanDefinition);
        //注册Pen的BeanDefinition
        GenericBeanDefinition penBeanDefinition = new GenericBeanDefinition();
        penBeanDefinition.setBeanClass(Pen.class);
        penBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
        penBeanDefinition.setInitMethodName("customInit");//设置初始化方法
        //设置pen属性
        penBeanDefinition.setPropertyValues(new MutablePropertyValues()
                .addPropertyValue(new PropertyValue("name", "英雄钢笔"))
        );
        context.registerBeanDefinition("pen", penBeanDefinition);//注册BeanDefinition
        //注册BookProxyInstantiationAwareBeanPostProcessor后处理器
        context.registerBean(BookProxyInstantiationAwareBeanPostProcessor.class);
        //刷新容器
        context.refresh();
        //获取Book的bean对象,调用show()方法
        context.getBean("book", Book.class).show();
    }

    static class Book implements InitializingBean {
        private String name;
        private String author;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }

        public void show() {
            System.out.printf("book#show():%s\n", this);
        }

        public void customInit() {
            System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Book#customInit", this.getClass().getSimpleName(), this);
        }

        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    ", author='" + author + '\'' +
                    '}';
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
        }
    }

    static class Pen implements InitializingBean {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Pen{" +
                    "name='" + name + '\'' +
                    '}';
        }

        public void customInit() {
            System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Pen#customInit", this.getClass().getSimpleName(), this);
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Pen#afterPropertiesSet", this.getClass().getSimpleName(), this);
        }
    }
}
执行结果


从执行结果即可反应出InstantiationAwareBeanPostProcessor的执行流程:

1~3行的结果是加载Book的输出,由于BookProxyInstantiationAwareBeanPostProcessor在执行postProcessBeforeInstantiation方法之后返回了Book的代理对象,所以后续对Book的所有初始化将不再继续,调用了BeanDefinition#postProcessAfterInitialization之后就直接返回注册了。
4~10行的输出结果可以看出,Pen类的加载,由于没有任何InstantiationAwareBeanPostProcessor对其做任何处理,所以走完了所有的常规Bean加载流程。
最后三行输出执行了从容器中获取的book对象的show()方法,可以看出我们通过BookProxyInstantiationAwareBeanPostProcessor成功的改变了原本注入到容器中的Book对象,并成功对其show()方法进行了增强处理。

源码解析


spring版本:5.2.9

该节源码解析仅仅只讲关键的与InstantiationAwareBeanPostProcessor相关的位置。如果想要知其与InstantiationAwareBeanPostProcessor前后的细节,可以针对本节的所讲述的位置自行Debug进入详细阅读。

首先是Spring容器的经典入口:refresh()

然后调用AbstractApplicationContext所持有的实际BeanFactory(DefaultListableBeanFactory)句柄的preInstantiateSingletons()做Bean容器的初始化工作。


org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons:
bean的创建流程:getBean()->doGetBean()->createBean()->doCreateBean()
我们直接定位到createBean()


从上面的流程可以看出,当执行了resolveBeforeInstantiation(beanName,mbdToUse)方法后,有返回bean对象,则直接return出去了。
如果没有返回bean对象,则会执行doCreateBean()进行真正的常规创建流程。

在本文章的例子中,初始化book对象的流程中BookProxyInstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()返回了book的代理对象,所以在上面的流程中,直接返回出去了,没有执行doCreateBean()方法。

接下进入resolveBeforeInstantiation(beanName,mbdToUse)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

createBean()将对象返回出去,一路回到getSingleton():
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory)

可以看到此时,已经将一个经过了InstantiationAwareBeanPostProcessor处理的Bean对象注册到了BeanFactory中(在本例子里面是我们的BookProxyInstantiationAwareBeanPostProcessor创建的Book对象的代理类)。


经过以上流程可以看出,当InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()如果返回了对象的话,那么Bean的创建流程将会直接结束返回该对象。


接下来讲InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()不返回对象的Bean创建流程,在该例子里面是Pen的创建流程:

上面的流程中,由于执行了BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()没有返回对象,所以会执行后面的doCreateBean()来创建对象。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

在上面的流程中,先通过反射创建了对象,然后调用populateBean()进行属性装配,属性装配后,执行Bean的初始化流程,包含了BeanPostProcessor的前后置处理、init-method相关处理。

我们知道,在InstantiationAwareBeanPostProcessor中目前还只执行了postProcessBeforeInstantiation(),还有剩下postProcessAfterInstantiation()postProcessProperties()postProcessBeforeInitialization()postProcessAfterInitialization()没有执行。

我们先看populateBean()中的逻辑:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

从上面的流程可以看出,populateBean()的流程是先调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(),然后调用其InstantiationAwareBeanPostProcessor#postProcessPropertyValues(),最后进行属性的装配工作。
此时和我们前面描述的执行流程保持一致。


接下来是postProcessBeforeInitialization()postProcessAfterInitialization()的执行还没有做。
返回到上层

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition):

从上面的initializeBean()的流程可以看到我们首先调用了BeanPostProcessor#postProcessBeforeInitialization(),然后执行了invokeInitMethods()来处理bean的实现的InitializingBean接口的afterPropertiesSet()与自定义init-method;最后执行BeanPostProcessor#postProcessAfterInitialization();

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization


org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

从上面的invokeInitMethods()可以看到包含了InitializingBean接口的处理与init-method的方法处理流程;
init-method方法最终会通过反射执行。

最后就是BeanPostProcessor#postProcessAfterInitialization()方法的执行:

至此,所有的InstantiationAwareBeanPostProcessor接口涉及到的流程都执行完毕,与前面讲述的流程一样,最后就是返回到getSingleton()将最后最终的对象注册到容器中。

总结

以上通过围绕InstantiationAwareBeanPostProcessor创建一个对指定Bean对象的代理对象,对其特定方法进行代理增强的例子,来介绍了InstantiationAwareBeanPostProcessor的应用,以及描述了InstantiationAwareBeanPostProcessor的"短路"会控制到后续常规Bean的创建流程。
同时,通过对源码的浅析来对InstantiationAwareBeanPostProcessor的执行前后流程进行了讲解。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/872103.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存