spring 后置处理器BeanFactoryPostProcessor和BeanPostProcessor的用法和区别

本文通过示例对比了BeanFactoryPostProcessor与BeanPostProcessor的主要区别:前者可以在初始化前修改Bean的配置信息,后者则是在Bean初始化前后进行处理。通过测试输出可以看到BeanFactoryPostProcessor的回调更早,且能够更改Bean实例的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

主要区别就是: BeanFactoryPostProcessor可以修改BEAN的配置信息而BeanPostProcessor不能,下面举个例子说明

BEAN类:

package com.springdemo.postProcessor;

public class PostProcessorBean {
	private String username;
	
	private String password;

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}
}


MyBeanPostProcessor类,实现了BeanPostProcessor接口:

package com.springdemo.postProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import com.springdemo.form.LoginForm;

public class MyBeanPostProcessor implements BeanPostProcessor {

	
	
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		// TODO Auto-generated method stub
		//如果是PostProcessorBean则username信息
		if(bean instanceof PostProcessorBean)
		{
			System.out.println("PostProcessorBean Bean initialized");
			PostProcessorBean pb = (PostProcessorBean)bean;
			
			System.out.println("username:"+pb.getUsername());
		}
		return bean;
	}

	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		// TODO Auto-generated method stub
		if(bean instanceof PostProcessorBean)
		{
			System.out.println("PostProcessorBean Bean initializing");
			PostProcessorBean pb = (PostProcessorBean)bean;
			
			System.out.println("username:"+pb.getUsername());
		}
		return bean;
	}

}


MyBeanFactoryPostProcessor实现了BeanFactoryPostProcessor接口:

package com.springdemo.postProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {
		// TODO Auto-generated method stub
		//BeanFactoryPostProcessor可以修改BEAN的配置信息而BeanPostProcessor不能
		//我们在这里修改postProcessorBean的username注入属性
		BeanDefinition bd = beanFactory.getBeanDefinition("postProcessorBean");
		MutablePropertyValues pv =  bd.getPropertyValues();
		if(pv.contains("username"))
		{
			pv.addPropertyValue("username", "xiaojun");
		}
		
	}

}


编写测试用例:

package com.springdemo.test;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.springdemo.factory.ApplicationContextFactory;

import com.springdemo.postProcessor.PostProcessorBean;

import junit.framework.TestCase;

public class BeanPostPorcessorTest extends TestCase {
	private ApplicationContext context;
	protected void setUp() throws Exception {
		super.setUp();
		String[] paths = {"classpath*:/spring/applicationContext-*.xml"};

		context = new ClassPathXmlApplicationContext(paths);
		
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}
	
	public void testBeanPostProcessor()
	{
		
	}
	public void testBeanFactoryPostProcessor()
	{
		//PostProcessorBean bean =(PostProcessorBean)ServiceLocator.getService("postProcessorBean");
		PostProcessorBean bean =(PostProcessorBean)context.getBean("postProcessorBean");
		System.out.println("---------------testBeanFactoryPostProcessor----------------");
		System.out.println("username:"+bean.getUsername());
		System.out.println("password:"+bean.getPassword());
		//
	}
}


spring配置文件如下(先不启用MyBeanFactoryPostProcessor):

<?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-2.0.xsd">
	
	<bean class="com.springdemo.postProcessor.MyBeanPostProcessor"></bean>
	<!--我们先把BeanFactoryPostProcessor注释掉,不启用,然后查看测试输出结果  
	<bean class="com.springdemo.postProcessor.MyBeanFactoryPostProcessor"></bean>
	-->
	<bean id="postProcessorBean" class="com.springdemo.postProcessor.PostProcessorBean" >
		<property name="username" value="test"></property>
		<property name="password" value="test"></property>
	</bean>
</beans>


测试输出结果如下:

PostProcessorBean Bean initializing
username:test
PostProcessorBean Bean initialized
username:test
---------------testBeanFactoryPostProcessor----------------
username:test
password:test

然后我们取消注释启用MyBeanFactoryPostProcessor,测试结果如下:

PostProcessorBean Bean initializing
username:xiaojun
PostProcessorBean Bean initialized
username:xiaojun
---------------testBeanFactoryPostProcessor----------------
username:xiaojun
password:test

从结果可以看出:BeanFactoryPostProcessor的回调比BeanPostProcessor要早,因为BeanPostProcess中输出的username已经变成了xiaojun,而不是test.还有就是BeanFactoryPostProcessor确实有能力改变初始化BEAN的内容,您可以试试在MyBeanPostProcess中试一试set一下username看看能不能改变BEAN实例的内容(答案应该是否定的).

Spring中的前置处理器后置处理器是用来在Bean的实例化初始化过程中进行一些额外的处理的。前置处理器是BeanFactoryPostProcessor接口的实现类,它在Spring容器加载Bean的定义之后,实例化Bean之前进行一些配置的修改或者其他操作。它可以对Bean的定义进行解析修改,最终将修改后的Bean定义添加到SpringBeanDefinitionMap中。\[1\]后置处理器BeanPostProcessor接口的实现类,它在Bean的实例化初始化过程中,对Bean进行一些额外的处理。它可以在Bean实例化后对Bean进行修改,也可以在Bean初始化前后对Bean进行一些操作,比如动态代理等。\[2\]在调用前置处理器的时候,Spring会按照优先级进行分类调用。实现了PriorityOrdered接口的前置处理器会先被调用,然后是实现了Ordered接口的前置处理器,最后是没有实现这两个接口的前置处理器。\[3\]这样可以确保前置处理器按照指定的顺序进行调用,以满足不同的需求。 #### 引用[.reference_title] - *1* *3* [攀登Spring珠穆朗玛峰:前置与后置处理器](https://blog.csdn.net/qq_38289451/article/details/122226807)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Spring Bean前置后置处理器的使用](https://blog.csdn.net/weixin_40834464/article/details/82832173)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值