Spring BeanPostProcessor后处理器源码解析
作者:保持敬畏
这篇文章主要介绍了Spring BeanPostProcessor后处理器源码解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
Spring后处理器-BeanPostProcessor
- Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过bean的初始化过程((该后处理器的执行时机)),例如:属性的填充、初始化方法init的执行等,其中有一个对外拓展的点BeanPostProcessor,我们称之为bean后处理器。与上文bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor(即在配置文件中对其进行配置),会在流程节点上被Spring自动调用。
- BeanPostProcessor接口代码如下
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; import org.springframework.lang.Nullable; public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
创建实现该接口(BeanPsotProcessor)的类,要在配置文件中进行管理
快捷键 ctrl + insert 重写接口方法
package com.example.PostProcessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName + ":postProcessBeforeInitialization"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName + ":postProcessAfterInitialization"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
测试类代码
package com.example.Test; import com.example.Service.Impl.UserServiceImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApplicationContext { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); System.out.println(context.getBean(UserServiceImpl.class)); } }
运行结果如下
展示了该后处理器的执行时机
Before和After执行时机
在Bean实例化过程可以配置相关对于bean对象的操作方法,具体间往期文章:Bean的配置
注册为bean的类
package com.example.Service.Impl; import com.example.DAO.UserDAO; import com.example.Service.UserService; import org.springframework.beans.factory.InitializingBean; import java.util.List; import java.util.Map; import java.util.Set; public class UserServiceImpl implements UserService, InitializingBean { // todo 无参构造方法 public UserServiceImpl() { System.out.println("UserServiceImpl实例化"); } // todo 自定义初始化方法 public void init() { System.out.println("自定义初始化方法init()"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("属性设置之后执行afterPropertiesSet()"); } }
实现bean后处理器的类
package com.example.PostProcessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName + ":postProcessBeforeInitialization"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName + ":postProcessAfterInitialization"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean class="com.example.PostProcessor.MyBeanPostProcessor"></bean> <bean id="userService" class="com.example.Service.Impl.UserServiceImpl" init-method="init"> </beans>
测试类
package com.example.Test; import com.example.Service.Impl.UserServiceImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApplicationContext { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); System.out.println(context.getBean(UserServiceImpl.class)); } }
运行结果
小结
从上述运行结果来看,首先完成bean对象的创建,然后执行后处理器中的before方法,然后执行属性设置之后的方法,然后执行自定义的初始化方法,最后执行后处理器的after方法
案例
- 对Bean方法进行执行时间日志增强
- 要求
- Bean的方法执行之前控制台打印当前时间
- Bean的方法执行之后控制台打印当前时间
- 分析
- 对方法进行增强主要就是代理设计模式和包装设计模式
- 由于Bean方法不确定,所以使用动态代理在运行期间执行增强操作
- 在Bean实例创建完毕之后,进入到单例之前,使用Proxy真实的目标bean
- 具体代码如下
代理类(实现了bean后处理接口)
package com.example.PostProcessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Date; public class TimeLogBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // todo 使用动态代理对目标bean进行增强,返回proxy对象,进而存储到单例池singletonObjects中 Object beanProxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), (InvocationHandler) (proxy, method, args) -> { // 输出开始时间 System.out.println("方法" + method.getName() + "开始执行时间" + new Date()); // 执行目标方法 Object rs = method.invoke(bean, args); // 输出结束时间 System.out.println("方法" + method.getName() + "结束执行时间" + new Date()); return rs; }); return beanProxy;// 将增强的bean存入单例池中 } }
bean对象对应的类
package com.example.Service.Impl; import com.example.Service.UserService; public class UserServiceImpl implements UserService { public void show() { System.out.println("show......"); } }
接口类
package com.example.Service; public interface UserService { public void show(); }
配置文件
<?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.example.PostProcessor.TimeLogBeanPostProcessor"></bean> <bean id="userService" class="com.example.Service.Impl.UserServiceImpl"> </bean> </beans>
测试类
package com.example.Test; import com.example.Service.UserService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApplicationContext { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); UserService UserServiceBean = (UserService) context.getBean(UserService.class); UserServiceBean.show(); } }
运行结果
Bean实例化基本流程图
首先通过Reader读取配置文件,解析bean标签,然后将每个bean标签变成beanDefinition对象存储到beanDefinitionMap中,然后经过所有的BeanFactoryPostProcessor(bean工厂后处理器),再从Map中取出每个beanDefiniton对象,通过反射变成Object对象,创建完对象后,经过beanPoatProcessor中的before方法和after方法(之间还存在bean中的init方法,后面会讲述),最终存入单例池中。
到此这篇关于Spring BeanPostProcessor后处理器的文章就介绍到这了,更多相关Spring BeanPostProcessor后处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!