使用spring的特殊bean --- 对bean进行后处理和对bean工厂进行后处理简单了解

本文介绍了Spring框架中BeanPostProcessor和BeanFactoryPostProcessor的作用及使用方法。BeanPostProcessor允许开发者在Bean实例化后进行定制化的操作,而BeanFactoryPostProcessor则可以在Bean实例化前对BeanFactory进行后处理。

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

使用spring的特殊bean  ---  对bean进行后处理和对bean工厂进行后处理简单了解

1.对bean进行后处理
后处理是在bean实例化以及装配完成之后发生的,在bean被创建以及装配之后,BeanPostProcessor提供了两次修改bean的机会,来对bean进行后处理操作。
程序清单 :我们来创建一个类来继承BeanPostProcessor接口来测试:

public class PersonServiceBean implements BeanPostProcessor,
		BeanFactoryPostProcessor {
	public PersonServiceBean() {
		super();
		System.out.println("构造函数的执行============");
	}
	// 初始化bean after之后的操作
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		// 传过来的beanName,也就是id是不可以改的
		// 通过bean的类型处理
		if (bean instanceof PersonServiceBean) {
			System.out.println("=====在被创建之后装配之后处理操作最后一次修改==========after"
					+ bean + "========" + beanName);
		}
		return bean;
	}

	// 初始化bean之前
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		// TODO Auto-generated method stub
		// 处理bean之前完成的一些操作
		if (bean instanceof PersonServiceBean) {
			System.out.println("========在被创建之后装配之后处理操作第一次修改=======before"
					+ bean + "========" + beanName);
		}
		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-2.5.xsd" default-lazy-init="true">
	<!-- default-lazy-init="true" 使用的时候在初始化 -->
	<!-- 配置一个bean实例,bean的创建配置及维护都交给了容器管理 -->
	<!-- 如果是默认的单列,执行一次,在容器初始化的时候执行
prototype 每次请求都触发一次 ,在调用后处理方法的时候要用他,因为它是在每次发送请求都会执行一次	
 -->
	<bean id="personServiceBean" class="cn.csdn.hr.service.PersonServiceBean" scope="prototype"></bean>
</beans>

测试:
public void test() {
		//读取配置文件,创建一次  初始化的时候会执行一次构造方法,在调用getBean的时候会再次执行构造方法
		ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"anbeans.xml"});
		PersonServiceBean personServiceBean = (PersonServiceBean) ac.getBean("personServiceBean");
	}

通过以上的代码可以看出实现了两个方法,分别为:postProcessAfterInitialization和postProcessBeforeInitialization,在xml中没有scope="prototype"的情况下,
只会调用无参构造,如果加上此属性,才可以把自己写的bean后处理的类中实例的方法写出来。
	default-lazy-init="true" 在使用的时候再初始化

输出的结果为:

构造函数的执行============
2012-4-18 4:52:57 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9f671b: defining beans [personServiceBean]; root of factory hierarchy
构造函数的执行============
========在被创建之后装配之后处理操作第一次修改=======beforecn.csdn.hr.service.PersonServiceBean@73a7ab========personServiceBean
=====在被创建之后装配之后处理操作最后一次修改==========aftercn.csdn.hr.service.PersonServiceBean@73a7ab========personServiceBean



2.对bean工厂进行后处理
对bean工厂进行操作的是BeanFactoryPostProcessor,它是在bean工厂载入所有的bean的定义后,并且在实例化bean之前,对bean的工厂做一些后处理操作
	程序清单: StudentServiceBean.java 
public class StudentServiceBean implements BeanFactoryPostProcessor{
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
			throws BeansException {
		System.out.println("处理操作================");
	}
}

我们要在xml中进行配置:
<bean 
id="studentServiceBean" class="cn.csdn.hr.service.StudentServiceBean"></bean>

这样,当我们再次运行的时候看到的结果为:

处理操作================
构造函数的执行============
2012-4-18 4:59:15 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9f671b: defining beans [personServiceBean,studentServiceBean]; root of factory hierarchy
构造函数的执行============
========在被创建之后装配之后处理操作第一次修改=======beforecn.csdn.hr.service.PersonServiceBean@1c86be5========personServiceBean
=====在被创建之后装配之后处理操作最后一次修改==========aftercn.csdn.hr.service.PersonServiceBean@1c86be5========personServiceBean

可以看出BeanFactoryPostProcessor的执行的位置是在初始化之前

### Spring Boot 中 `spring.main.allow-bean-definition-overriding` 属性的作用 在 Spring Boot 应用程序中,`spring.main.allow-bean-definition-overriding=true` 是一个用于控制 Bean 定义覆盖行为的关键属性。默认情况下,在 Spring 的上下文中不允许存在相同名称的两个 Bean 定义,如果发生这种情况,则会抛出异常。然而,当此属性被显式设置为 `true` 后,允许后续注册的 Bean 覆盖已经存在的同名 Bean[^1]。 #### 原理分析 该属性的核心作用在于调整容器内的 Bean 注册逻辑。具体来说,Spring 容器内部维护了一个名为 `DefaultListableBeanFactory` 的类来管理所有的 Bean 实例及其元数据。在这个过程中,`allowBeanDefinitionOverriding` 参数决定了是否允许新的 Bean 定义替换已有的定义。如果设置了 `spring.main.allow-bean-definition-overriding=true`,则会在检测到重复 Bean 名称时执行覆盖操作而不是报错[^2]。 #### Bean 加载顺序的影响 需要注意的是,即使启用了 `spring.main.allow-bean-definition-overriding=true`,实际的覆盖效果还取决于 Bean 配置文件或 Java Config 类加载的先后次序。通常情况下,Spring 会按照如下优先级处理 Bean: 1. **手动编写的 Configuration 文件中的 @Bean 方法**:这些方法会被尽早解析并注册。 2. **自动装配组件扫描发现的 Beans**:通过 `@ComponentScan` 或其他机制找到的类将稍晚一些加入到上下文中。 3. **外部化配置(如 application.yml/properties)指定的内容**:这类配置可能进一步延迟应用时间点。 因此,最终哪个版本的 Bean 生效往往由谁最后完成注册决定。例如,假设 A B 都试图提供名字相同的某个服务接口实现类实例给 IoC 容器,而 A 出现在更前面的位置,那么除非另有特殊安排,默认情形下应该是 B 取代了 A 成为了唯一可用的选择项[^4]。 另外值得注意的一点是,虽然启用这个选项可以帮助调试某些复杂场景下的依赖冲突问题,但它也可能隐藏潜在的设计缺陷或者编程失误——比如无意间引入多个功能相似却互斥的服务变体。所以官方文档建议谨慎使用此项特性,并鼓励开发者尽量保持项目结构清晰合理以减少不必要的麻烦[^3]。 ```yaml # Example of enabling override in application.yml spring: main: allow-bean-definition-overriding: true ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值