spring步步前行(IOC)-强撸BeanFactoryPostProcessor

spring步步前行(IOC)-强撸BeanFactoryPostProcessor

spring为我们提供的一些由我们自由控制时机的方式除了BeanPostProcessor外,还有一个叫BeanFactoryPostProcessor,我们知道BeanFactoryPostProcessor其作用是允许我们在工厂内所有的bean没被初始化之前且在加载后,对所有bean的属性进行修改,相信很多朋友对其作用和意义也是停留在看看,这一篇我们继续使用一些实例辅助我们理解BeanFactoryPostProcessor

官方解读

在这里插入图片描述

这个接口是允许修改应用上下文中的bean definitions来适配bean的属性值,其也就是说spring在初始化beanDefinitionMap后为我们提供了一个允许我们修改beanDefinition内容的契机

感觉和上一篇我们分析的beanPostProcessor很相像,我们再回头将beanPostProcessor的官方注释结合起来看看beanPostProcessor与beanFactoryPostProcessor有什么不同

首先beanPostProcessor

Factory hook that allows for custom modification of new bean instances,
e.g. checking for marker interfaces or wrapping them with proxies.
允许修改新的bean的实例  

而beanFactoryPostProcessor官方是这样描述的

A BeanFactoryPostProcessor may interact with and modify bean
definitions, but never bean instances. 
即beanFactoryPostProcessor是修改deanDefinitions而不是修改实例

从这里我们很清晰的能看出它们俩的不同,beanFactoryPostProcessor修改的是beanDefinition,而beanPostProcessor修改的是bean的实例。那bean的实例与beanDefiniton的关系又是什么呢?从之前的beanFactory的分析,我们了解到beanDefinition是对bean的描述,举个例子也就是说一个公司打印海报,发现海报上的公司信息有问题,beanPostProcessor的做法就是直接划掉换上新的,而beanFactoryPostProcessor的做法就是直接重新做一份海报,到这beanFactoryPostProcessor与beanPostProcessor的区别就很明显了,beanFactoryPostProcessor完全修改属性,而beanPostProcessor更像临时修改bean的属性

这里我们简单回顾下beanDefinition:

在这里插入图片描述

beanDefinition是对bean实例的描述,包括是否单例,是否抽象,是否懒加载属性,构造参数等信息,其通过继承AttributeAccessor赋予了其具备操作属性相关的方法,继承BeanMetadataElement来持有bean元数据元素的持有,总的来说就是将bean的信息存储到这个BeanDefinition相应的属性中,可根据其信息来反射创建对象

接下来我们看看beanFactoryPostProcessor的接口方法:

在这里插入图片描述

既然beanFactoryPostProcessor修改的是beanDefinition,而我们的beanDefinition又存储在beanFactory内,那么自然我们要方法上就需要beanFactory作为参数了

实例

既然和beanPostProcessor很相近,那我们继续沿用之前的demo好了,对于在beanPostProcessor的我们添加默认值的做法,可能有很多朋友对注解处理觉得不够优雅,这一次我们改用beanFactoryPostProcessor来实现达到同样的效果

首先对我们创建的调试bean做调整:

//去掉默认值的注解不在需要,注意提供set方法不然会报错
public class ClazzBean {

//    @SetDefaultValue(defaultValue = "章三")
    public String name;
    public String clazz;
    public String extral;

//    @SetDefaultValue(defaultValue = "17213213")
    public String phone;

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

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public void setExtral(String extral) {
        this.extral = extral;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "ClazzBean{" +
                "name='" + name + '\'' +
                ", clazz='" + clazz + '\'' +
                ", extral='" + extral + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}
		@Bean("clazzbean")//添加标记 后续通过clazzbean来获取beanDefinition
    public ClazzBean test() {
        return new ClazzBean();
    }

然后对之前的BeanPostProcessor的postProcessBeforeInitialization内处理注解方法注释不在需要

接着我们创建一个实现了BeanFactoryPostProcessor的Processor类,如下:

在这里插入图片描述

我们的改造就完毕了,跑起来爽一下看看效果:

在这里插入图片描述

果然达到同样的效果,是不是优雅很多,一个字,爽!!

官例介绍

上一次我们举例了spring中为我们提供了很多我们可以学习的实例,毕竟耳听为虚,眼见为实,这一次我们通过官方的一个beanFactoryPostProcessor的实现来眼见为实一次

我们以一个过时警告的应用举例子:

来自于org.springframework.beans.factory.config的DeprecatedBeanWarner,其作用是通过Deprecated注解来过滤警告我们有些类已经过期了,请注意

我们看看其实现:

在这里插入图片描述

首先Deprecated的功能简单,很容易一目了然,主要是postProcessBeanFactory和logDeprecatedBean这两个方法

在这里插入图片描述

首先先检查log是否启用,如果启用,那么通过beanFactory获取所有beanDefinitionNames,然后遍历,这里注意isFactoryBean这个方法如果是factoryBean的话,需要通过"&"+beanName的方法查找class(对于factorybean我们会再找一篇机会重点分析一下,毕竟是spring ioc几个关键组成),找到class后,看是否有Deprecated这个注解,如果有的话那么就进入logDeprecatedBean方法

在这里插入图片描述
这个方法就更简单了,将bean的信息打印出来,这样就完成了警告

以上就是spring内部对beanFactoryPostProcessor的简单应用,至此我们对beanFactory相信已经有了很深的印象,步步前行,扎实基础!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章