首页 > 其他分享 >Spring5 IOC容器解析——后置处理器PostProcessor

Spring5 IOC容器解析——后置处理器PostProcessor

时间:2023-01-07 18:32:30浏览次数:64  
标签:BeanPostProcessor beanName throws bean 实例 PostProcessor IOC public Spring5

后置处理器PostProcessor

其本身也是一种需要注册到容器中的Bean

  • 其里面的方法会在特定时机被容器调用
  • 实现不改变容器或者Bean核心逻辑的情况下对Bean进行扩展
  • 对Bean进行包装、影响其行为、修改Bean的内容等。

PostProcessor的种类

大致分为容器级别的后置处理器和Bean级别的后置处理器

  • BeanDefinitionRegistryPostProcessor:动态注册Bean到Spring容器。
  • BeanFactoryPostProcessor:Spring容器功能扩展的重要接口,例如修改bean属性值,实现bean动态代理等。
  • BeanPostProcessor:Bean后置处理器。
  • InstantiationAwareBeanPostProcessor:实例化Bean后置处理器(继承BeanPostProcessor)
  • SmartInstantiationAwareBeanPostProcessor:智能实例化Bean后置处理器(继承InstantiationAwareBeanPostProcessor)
  • MergedBeanDefinitionPostProcessor:合并Bean定义后置处理器(继承BeanPostProcessor)
  • DestructionAwareBeanPostProcessor:销毁Bean后置处理器(继承BeanPostProcessor)

BeanDefinitionRegistryPostProcessor

编写类实现BeanDefinitionRegistryPostProcessor往容器中注册额外的BeanDefinition实例 //下面分别是利用RootBeanDefinition和GenericBeanDefinition的两种写法

RootBeanDefinition

@Configuration
public class MyBeanRegister implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(User.class);
        beanDefinitionRegistry.registerBeanDefinition("user",rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

GenericBeanDefinition

@Configuration
public class MyBeanRegister implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        Class<?> clazz = User.class;
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		GenericBeanDefinition beanDefinition = (GenericBeanDefinition)builder.getRawBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("user",beanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfiguration.class})
public class CustomBeanDefinitionRegistryTest {

	@Autowired
	private TestBean testBean;
	
	@Test
	public void test() {
		Assert.assertNotNull(testBean);
	}
	
}

BeanFactoryPostProcessor

BeanFactory后置处理器,是对BeanDefinition对象进行修改。(BeanDefinition:存储bean标签的信息,用来生成bean实例)

public interface BeanFactoryPostProcessor {

	//可以通过beanFactory获取bean定义信息
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

BeanFactoryPostProcessor接口是针对bean容器的,它的实现类可以在当前BeanFactory初始化(spring容器加载bean定义文件)后,bean实例化之前修改bean的定义属性,达到影响之后实例化bean的效果。

 

也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。

使用方式:

public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    /**
     * 主要是用来自定义修改持有的bean
     * ConfigurableListableBeanFactory 其实就是DefaultListableBeanDefinition对象
     * @param beanFactory
     * @throws BeansException
     */

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用了自定义的BeanFactoryPostProcessor " + beanFactory);
        Iterator it = beanFactory.getBeanNamesIterator();

        String[] names = beanFactory.getBeanDefinitionNames();
        // 获取了所有的bean名称列表
        for(int i=0; i<names.length; i++){
            String name = names[i];

            BeanDefinition bd = beanFactory.getBeanDefinition(name);
            System.out.println(name + " bean properties: " + bd.getPropertyValues().toString());
            // 本内容只是个demo,打印持有的bean的属性情况
        }
    }
}

BeanPostProcessor

Bean后置处理器,是对生成的Bean对象进行修改。 该类源码如下:

public interface BeanPostProcessor {

     //bean初始化之前调用
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    //bean初始化之后调用
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

BeanPostProcessor能在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。初始化方法包括以下两种:

  • 1、实现InitializingBean接口的bean,对应方法为afterPropertiesSet
  • 2、xml定义中,通过init-method设置的方法

如果自定义了多个的BeanPostProcessor的实现类,通过实现Ordered接口,设置order属性,可以按照顺序执行实现类的方法。

 

BeanPostProcessor是BeanFactoryPostProcessor之后执行的。

spring中bean的生命周期如下图

InstantiationAwareBeanPostProcessor

关于对象实例化前后以及实例化后设置propertyValues的回调

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    //这个方法用来在对象实例化前直接返回一个对象(如代理对象)来代替通过内置的实例化流程创建对象;
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    //在对象实例化完毕执行populateBean之前 如果返回false则spring不再对对应的bean实例进行自动依赖注入。
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }
    //这里是在spring处理完默认的成员属性,应用到指定的bean之前进行回调,可以用来检查和修改属性,最终返回的PropertyValues会应用到bean中
    //@Autowired、@Resource等就是根据这个回调来实现最终注入依赖的属性的。
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
}

SmartInstantiationAwareBeanPostProcessor

这个接口主要是spring框架内部来使用

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    //用来返回目标对象的类型(比如代理对象通过raw class获取proxy type 用于类型匹配)
    @Nullable
    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的引用,用来支持单例对象的循环引用(一般是bean自身,如果是代理对象则需要取用代理引用)
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

MergedBeanDefinitionPostProcessor

用来将merged BeanDefinition暴露出来的回调

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
    //在bean实例化完毕后调用 可以用来修改merged BeanDefinition的一些properties 或者用来给后续回调中缓存一些meta信息使用
    //这个算是将merged BeanDefinition暴露出来的一个回调
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}

DestructionAwareBeanPostProcessor

关于处理对象销毁的前置回调 应用实例: ApplicationListenerDetector,这个类是用来注册ApplicationListener实例的,而如果销毁一个对象,不接触这里的引用会导致无法进行回收,因此在销毁对象时,会判断如果是ApplicationListener要执行从监听器列表中移除掉。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    //这里实现销毁对象的逻辑
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
    //判断是否需要处理这个对象的销毁
    default boolean requiresDestruction(Object bean) {
        return true;
    }
}

关于BeanPostProcessor中各个回调调用的顺序

  • 1、InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(beanClass, beanName) 该方法在创建对象之前会先掉用,如果有返回实例则直接使用不会去走下面创建对象的逻辑,并在之后执行BeanPostProcessor.postProcessAfterInitialization(result, beanName)
  • 2、SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors(beanClass, beanName) 如果需要的话,会在实例化对象之前执行
  • 3、MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName) 在对象实例化完毕 初始化之前执行
  • 4、InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName) 在bean创建完毕初始化之前执行
  • 5、InstantiationAwareBeanPostProcessor.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName) 在bean的property属性注入完毕 向bean中设置属性之前执行
  • 6、BeanPostProcessor.postProcessBeforeInitialization(result, beanName) 在bean初始化(自定义init或者是实现了InitializingBean.afterPropertiesSet())之前执行
  • 7、BeanPostProcessor.postProcessAfterInitialization(result, beanName) 在bean初始化(自定义init或者是实现了InitializingBean.afterPropertiesSet())之后执行
  • 8、其中DestructionAwareBeanPostProcessor方法的postProcessBeforeDestruction(Object bean, String beanName)会在销毁对象前执行

DestructionAwareBeanPostProcessor 中的requiresDestruction(Object bean)是用来判断是否属于当前processor处理的bean SmartInstantiationAwareBeanPostProcessor中的predictBeanType(Class<?> beanClass, String beanName)是用来预判类型的 SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(exposedObject, beanName) 这个方法仅仅是在这一步是作为一个ObjectFactory封装起来放到singletonFactories中的,仅在并发情况下 刚好在当前对象设置进去,而另一个bean创建需要getBean获取时才会立即执行,因此这一步的顺序是不一定的,有可能永远不会执行(无并发循坏依赖对象创建的场景),可能在3之后对象实例化完毕执行addSingleton(beanName, singletonObject);之前执行到,因此这三个方法没有严格的顺序意义。

 

参考: https://www.cnblogs.com/MichaelPL/p/11631034.html

https://blog.csdn.net/zhanyu1/article/details/83114684

https://www.cnblogs.com/cmfwm/p/7728174.html

https://www.cnblogs.com/zhangjianbin/p/10059191.html

标签:BeanPostProcessor,beanName,throws,bean,实例,PostProcessor,IOC,public,Spring5
From: https://blog.51cto.com/u_14014612/5995709

相关文章

  • Spring5 IOC容器解析——Aware接口
    AwareAware是Spring中的一个根接口,继承该接口的子接口有很多,但是该接口没有任何方法,所以大家可以把它理解成一个标记接口: Spring框架中提供了许多实现了Aware接口的......
  • Spring5 IOC容器解析——事件监听机制
    一、事件驱动模型简介事件驱动模型,也即是我们通常说的观察者。基于发布-订阅模式的编程模型。概念定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖......
  • Spring5 IOC容器解析——BeanDefinitionReader
    概述BeanDefinitionReader的作用是读取Spring配置文件中的内容,将其转换为IOC容器内部的数据结构:BeanDefinition。在前面章节关于BeanDefinition的学习中有提到XmlB......
  • Spring5 IOC容器解析——BeanDefinition的注册
    前言在上一篇文章解析BeanDefinition对配置文件解析完成后,获取的beanDefiniton已经可以进行使用了,剩下的唯一工作就是注册了,也就是processBeanDefinition方法中的BeanDefi......
  • Spring IOC官方文档学习笔记(七)之Bean Definition继承
    1.BeanDefinition继承(1)Spring中的bean存在层级关系,我们可以定义子bean来继承或覆盖父bean中的某些属性,从而节省编码,在此处Spring运用到了模板设计模式,如下所示//自定......
  • ioctl(skfd, request, pwrq)
    /*------------------------------------------------------------------*//**WrappertoextractsomeWirelessParameteroutofthedriver*/staticinlinein......
  • spring5框架
    概述:Spring是轻量级的开源的JavaEE框架Spring可以解决企业应用开发的复杂性Spring有两个核心部分:IOC和AOPIOC:控制反转,把创建对象过程交给Spring进行管理AOP:面向切面......
  • Spring IOC官方文档学习笔记(六)之自定义bean的特性
    1.生命周期回调(1)如果我们想要介入bean的生命周期,可通过实现spring中的InitializingBean和DisposableBean接口来达到这一目的,spring会调用InitializingBean中的afterPro......
  • spring 基础知识-- IOC 和 DI 的配置和使用。
    目录​​一、基本概念​​​​二、Spring核心概念 ​​​​1、问题分析​​​​2、IOC、IOC容器、Bean、DI​​​​3、IOC入门案例​​​​4、DI入门案例​​​​三、IO......
  • Spring注解:使用注解的方式完成IOC
    补充:xml配置最开始(Spring1.x),Spring都是通过xml配置控制层(controller)--业务逻辑层(service)--dao层--数据源的关系,但是比较复杂Spring2.x的时候,随着JDK1.5支持注解的方式,......