当前位置: 首页 > news >正文

Spring的后处理器

Spring的后处理器

源码

Spring 主要的两种后处理器

  • BeanFactoryPostProcessor : Bean 工厂后处理器,在BeanDefinitionMap 填充完毕,Bean 实例化之前执行;
  • BeanPostProcessor : Bean 后处理器,一般在 Bean 实例化之后,填充到单例池 SingletonObjects 之前执行;

BeanFactoryPostProcessorBeanDefinitionMap 中进行注册、修改操作

xml 文件配置

<?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.kaiming.processor.MyBeanFactoryPostProcessor"></bean><bean id="userDao" class="com.kaiming.dao.impl.UserDaoImpl"></bean><!-- userService中注入userDao--><bean id="userService" class="com.kaiming.service.impl.UserServiceImpl"></bean>
</beans>    
注册
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("beanDefinitionMap填充完成后回调该方法");        // 注册RootBeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.kaiming.dao.impl.PersonDaoImpl");DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;defaultListableBeanFactory.registerBeanDefinition("personDao", beanDefinition);}
}

test 获取 personDao

public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");Object personDao = beanFactory.getBean("personDao");System.out.println(personDao);}
}
beanDefinitionMap填充完成后回调该方法
com.kaiming.dao.impl.PersonDaoImpl@1e67a849
修改
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("beanDefinitionMap填充完成后回调该方法");BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");beanDefinition.setBeanClassName("com.kaiming.dao.impl.UserDaoImpl");}
}

test

public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");      Object userService = beanFactory.getBean("userService");System.out.println(userService);}
}
beanDefinitionMap填充完成后回调该方法
com.kaiming.dao.impl.UserDaoImpl@448ff1a8
BeanFactoryPostProcessor 的子接口

源码

主要用于 BeanDefinition 注册

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

一般注册 BeanDefinition 使用这个接口,不用针对 ConfigurableListableBeanFactory 进行强转

public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {RootBeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.kaiming.dao.impl.PersonDaoImpl");beanDefinitionRegistry.registerBeanDefinition("personDao", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
}

xml 文件配置 MyBeanDefinitionRegistryPostProcessor

<?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.kaiming.processor.MyBeanFactoryPostProcessor"></bean><bean class="com.kaiming.processor.MyBeanDefinitionRegistryPostProcessor"></bean><bean id="userDao" class="com.kaiming.dao.impl.UserDaoImpl"></bean><!-- userService中注入userDao--><bean id="userService" class="com.kaiming.service.impl.UserServiceImpl"></bean></beans>     

test

public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");Object personDao = beanFactory.getBean("personDao");System.out.println(personDao);}
}

实现了 去实现 BeanFactoryPostProcessor 接口达到同样的效果

com.kaiming.dao.impl.PersonDaoImpl@41ee392b

关于实现了 BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor 执行顺序

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("MyBeanFactoryPostProcessor的postProcessBeanFactory方法");}
}
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {System.out.println("MyBeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法");RootBeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.kaiming.dao.impl.PersonDaoImpl");beanDefinitionRegistry.registerBeanDefinition("personDao", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {System.out.println("MyBeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法");}
}
MyBeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
MyBeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
MyBeanFactoryPostProcessor的postProcessBeanFactory方法

BeanPostProcessor

Bean 被实例化后,到最终缓存到 SingletonObjects 单例池前,中间会经过 Bean 的初始化过程,例如:属性的填充,初始化 init 的执行等,其中有一个对外进行扩展的点 BeanPostProcessor ,称之为 Bean 后处理器。与 Bean 工厂后处理器相似,也是一个接口,实现了该接口并被容器管理的 BeanPostProcessor ,会在流程节点上被 Spring 自动调用。

// BeanPostProcessor 源码
public interface BeanPostProcessor {@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}

创建一个 MyBeanPostProcessor 类实现 BeanPostProcessor 接口

public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessAfterInitialization");return bean;}
}

xml 文件配置

<?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.kaiming.processor.MyBeanPostProcessor"></bean><bean id="userDao" class="com.kaiming.dao.impl.UserDaoImpl"></bean></beans>     

test

public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");Object userDao = beanFactory.getBean("userDao");}
}
postProcessBeforeInitialization
postProcessAfterInitialization
com.kaiming.dao.impl.UserDaoImpl@3c0a50da

我们为 UserDaoImpl 添加无参构造器,init 方法,afterPropertiesSet 方法(实现 InitializingBean 接口),观察执行顺序;

public class UserDaoImpl implements UserDao, InitializingBean {private String username;public void setName(String userName) {this.username = userName;}public UserDaoImpl() {System.out.println("userDao实例化");}public void init() {System.out.println("init初始化方法执行");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("属性设置之后执行");}
}

xml 文件配置

<?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.kaiming.processor.MyBeanPostProcessor"></bean><bean id="userDao" class="com.kaiming.dao.impl.UserDaoImpl" init-method="init"></bean></beans>     

test 测试

public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");Object userDao = beanFactory.getBean("userDao");System.out.println(userDao);}
}
userDao实例化
postProcessBeforeInitialization
属性设置之后执行
init初始化方法执行
postProcessAfterInitialization
com.kaiming.dao.impl.UserDaoImpl@797badd3

案例

Bean 方法进行执行时间日志增强

要求:

  • Bean 的方法执行前控制台打印当前时间;
  • Bean 的方法执行后控制台打印当前时间;

分析:

  • 对方法进行增强主要采用代理和包装设计模式
  • 由于 Bean 方法不确定,所以使用动态代理在运行期间执行增强操作;
  • Bean 实例创建完成后,进入单例池前,使用 Proxy 代替真正的目标 Bean ;
TimeLogBeanPostProcessor 实现 BeanPostProcessor
public class TimeLogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 使用动态代理对目标bean进行增强,返回Proxy对象,进而存储到SingletonObjects中Object beanProxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),(proxy, method, args) -> {// 输出开始时间System.out.println("方法: " + method.getName() + "-开始时间: " + LocalDateTime.now());// 执行目标方法Object results = method.invoke(bean, args);// 输出结束时间System.out.println("方法: " + method.getName() + "-结束时间: " + LocalDateTime.now());return results;});return beanProxy;}
}
xml 文件配置
<?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.kaiming.processor.TimeLogBeanPostProcessor"></bean><bean id="userDao" class="com.kaiming.dao.impl.UserDaoImpl"></bean></beans>     
userDao 接口 抽象方法
public interface UserDao {    void show();
}
userDaoImpl 实现 userDao 接口
public class UserDaoImpl implements UserDao {@Overridepublic void show() {System.out.println("show()...");}
}
test 测试
public class ApplicationContextTest {public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");UserDao userDao = (UserDao) beanFactory.getBean("userDao");userDao.show();}
}
方法: show-开始时间: 2025-10-25T12:00:57.305161400
show()...
方法: show-结束时间: 2025-10-25T12:00:57.306161200
http://www.dtcms.com/a/528351.html

相关文章:

  • 本地佛山顺德网站设计深圳市宝安区西乡街道
  • 监控 Linux 系统上的内存使用情况
  • 湖北省住房与建设厅网站高品质的网站开发
  • 智慧校园建设方案-6PPT(32页)
  • Spring的@Cacheable取缓存默认实现
  • MySQL-TrinityCore异步连接池的学习(七)
  • 2020应该建设什么网站建网站的论坛
  • 华为OD机考双机位A卷 - Excel单元格数值统计 (C++ Python JAVA JS GO)
  • SpringBoot集成Elasticsearch | Elasticsearch 7.x专属HLRC(High Level Rest Client)
  • 广东省住房城乡建设厅门户网站免费下载手机app
  • 信创入门指南:一文掌握信息技术应用创新的核心要点
  • 基于鸿蒙UniProton的物联网边缘计算:架构设计与实现方案
  • 基于Swin Transformer的脑血管疾病中风影像诊断系统研究
  • 宝安第一网站东莞关键词优化软件
  • 篮球论坛|基于SprinBoot+vue的篮球论坛系统(源码+数据库+文档)
  • SQL 进阶:触发器、存储过程
  • ansible快速准备redis集群环境
  • 公司网站制作效果长沙网站制造
  • 数据结构之堆
  • 【Linux学习笔记】日志器与线程池设计
  • 【Linux系统编程】编辑器vim
  • 鸿蒙ArkTS入门教程:小白实战“易经”Demo,详解@State、@Prop与List组件
  • 扩散模型与UNet融合的创新路径
  • 从入门到精通的鸿蒙学习之路——基于鸿蒙6.0时代的生态趋势与实战路径
  • 704.力扣LeetCode_二分查找
  • 如何做企业网站宣传wordpress 显示空白
  • 机器学习库的线性回归预测
  • 旅游网站开发研究背景北京欢迎您
  • 做网站要学什么东西企业网站运维
  • Orleans Grain Directory 系统综合分析文档