4、Spring的后处理器

Spring的后处理器允许介入Bean的实例化流程,包括BeanFactoryPostProcessor在Bean实例化前修改BeanDefinition,以及BeanPostProcessor在初始化后对Bean进行处理。这两个接口提供了动态注册和修改Bean的能力,可以实现如属性注入、方法增强等功能。文章通过示例解释了如何使用这些后处理器进行定制化操作。
摘要由CSDN通过智能技术生成

Spring的后处理器

Spring的后处理器是Spring对外开放的重要拓展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器:

1、BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;

2、BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行。

由此,通过Bean工厂后处理器,我们可以在<bean>标签被录入信息完毕后修改指定的bean信息,甚至自己添加bean信息,这样就绕过了xml配置的环节。

 Bean工厂后处理器——BeanFactoryPostProcessor

例1:利用BeanDefinition的getBeanDefinition方法动态修改BeanDefinition 

 xml文件中beanId为userService对应的bean实例为UserServiceImpl

 定义一个配置类实现BeanFactoryPostProcessor接口,修改id为userSerivce的BeanDefinition,将其对应的实例修改为UserDaoImpl

getBean去拿userSerive的实例 

 但是拿到的却是UserDaoImpl实例

 例2:利用BeanDifinition的子类——RootBeanDefinition动态注册BeanDefinition

这里第三行的被强转的beanFactory是形参。 

BeanDefinition beanDefinition = new RootBeanDefinition();

beanDefinition.setBeanClassName("com.itheima.dao.impl.PersonDaoImpl");

DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)beanFactory;

defaultListableBeanFactory.registerBeanDefinition("personDao",beanDefinition);

当然这个配置类得去xml中配置,Spring不能自己识别到这个配置类的

 Spring也提供了BeanDefinitionRegistryPostProcessor接口专门用于注册BeanDefinition操作。

 同样的,要去xml中配置这个配置类 

 Bean工厂后处理器

Bean后处理器

不同于Bean工厂后处理器,Bean后处理器开始于Bean被实例化后,并在实例化的Bean被缓存到单例池之前执行,中间经过Bean的初始化过程,包括:属性的填充、初始方法init的执行等,其中一个对外拓展的点接口BeanPostProcessor被称为Bean后处理,实现了该接口并被容器管理的配置类会在流程节点上被Spring自动调用。

实现BeanPostProcessor接口的配置类需要主动覆写两个方法,因为下面两个方法有@Nullable注解,所以要我们手动覆写:

porstProcessBeforeInitialization方法在属性注入完毕 后,init初始化方法执行之前被回调;

postProcessAfterInitialization方法在init初始化方法执行之后,被添加到单例池singletonObjects之前被回调。

 Bean后处理器快速入门

在init方法执行之前,把bean拿出来判断是不是UserDaoImpl,是的话就为其注入属性username=haohao

xml文件中配置Bean后处理器 

 Bean容器初始化

案例:时间日志功能增强

定义一个增强类实现BeanPostProcessor接口 

public class TimeLogBeanPostProcessor implements BeanPostProcessor {
    
    //重写after方法
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception{
        //使用动态代理对目标Bean进行增强,返回proxy对象,进而存储到单例池singletonObjects中
        Object beanProxy = Proxy.newProxyInstance(
            bean.getClass().getClassLoader(),
            bean.getClass().getInterfaces(),
            (proxy, method, args) -> {
                //在这里对目标Bean进行增强
                //1.输出开始时间
                System.out.println("方法:" + method.getName() + "-结束时间:" + new Date());
                //2.执行目标方法
                Object result = method.invoke(bean, args);
                //3.输出结束时间
                System.out.println("方法:" + method.getName() + "-结束时间:" + new Date());
                return result;
                
            }

        );
        return beanProxy;//返回增强后的目标Bean
    }
    
}

在xml中配置一个用于验证的Bean,配置我们的增强类 :

 用于验证的Bean:

 测试代码:

测试结果:

该增强类利用动态代理,对所有的Bean的所有方法的执行前后都增强了打印时间日志的功能。 

 继续完善实例化基本流程图 

以下是BeanPostProcessor在SpringBean的实例化过程中的体现

大体上,在ApplicationContext容器的环境下,在xml文件加载后,所有的<bean>标签内容都封装成BeanDefinition并将BeanDefinition存入beanDefinitionMap中,然后遍历beanDefinitionMap将bean实例化并存入singletonObjects单例池中,当调用getBean()时从单例池中去拿对象。

在学习完Spring的后处理器后我们可以知道,在遍历beanDefinitionMap拿出beanDefinition后,要先经过BeanFactoryPostProcessor(Bean工厂后处理器),然后通过反射变成一个对象Obj,在对象进入单例池之前,还要经过BeanPostProcessor(Bean后处理器)的before和after方法,最后才进入单例池中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值