Spring源码十:BeanPostProcess

news/2024/7/8 9:19:56 标签: spring, java, 后端

上一篇Spring源码九:BeanFactoryPostProcessor,我们看到ApplicationContext容器通过refresh方法中的postProcessBeanFactory方法和BeanFactoryPostProcessor类提供预留扩展点,他可以在Spring容器的层面对BeanFactroy或其他属性进行修改,所以我们经常说BeanFactoryPost Processor是Spring容器层面的一个扩展点。

但是,我们除了在容器层面外我们有没有粒度更小一点的扩展处理呢?比我们能否直接修改我们的Bean呢?

接下来咱们进入Spring给我们预留另外一个比较重要的扩展点,也就是我们bean的后置处理器BeanPost Processor。

BeanPostProcessor初探

在Spring框架中,BeanPostProcessor是一个核心接口,它允许我们在Spring容器实例化、配置和初始化Bean之前或之后进行一些额外的处理。通过实现这个接口,我们可以在Bean的生命周期的特定点插入自定义逻辑,以增强或修改Bean的行为。本文将深入探讨BeanPostProcessor的定义、用途、使用实例、注册方式以及其在Spring应用中的重要性和应用场景。

1. BeanPostProcessor接口定义

BeanPostProcessor接口定义了两个主要方法:

java">public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
  • postProcessBeforeInitialization:在Bean初始化之前被调用。这通常指的是在Bean的init-method或者实现了InitializingBean接口的afterPropertiesSet方法之前。
  • postProcessAfterInitialization:在Bean初始化之后被调用。

这些方法的主要作用是允许开发者在Bean的初始化过程中进行定制化处理,这种处理可以是对Bean属性的修改、添加日志、检查标记接口或对Bean进行代理等操作。

2. BeanPostProcessor的目的与应用

BeanPostProcessor的主要目的是通过改进Bean的初始化过程,提高Spring容器中Bean的管理和使用效率。具体应用场景包括:

  • 属性修改:在Bean初始化之前或之后,对Bean的某些属性进行修改,以满足特定需求。
  • 日志记录:在Bean的初始化过程中,记录日志信息,以便于调试和监控。
  • 标记接口检查:检查Bean是否实现了特定的标记接口,并根据检查结果进行相应处理。
  • 代理增强:对Bean进行代理,以添加额外的功能,例如AOP(面向切面编程)中的增强功能。
3. BeanPostProcessor使用实例

下面是一个简单的使用实例,展示了如何在Bean初始化前后添加日志:

java">@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before Initialization: " + beanName);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After Initialization: " + beanName);
        return bean;
    }
}

在这个例子中,我们实现了BeanPostProcessor接口,并在postProcessBeforeInitializationpostProcessAfterInitialization方法中分别添加了日志输出。这使得每当一个Bean在初始化之前或之后,这两个方法都会被调用,并输出相应的日志信息。

4. BeanPostProcessor的注册

要使BeanPostProcessor生效,必须将其注册到Spring容器中。注册方式有多种,包括注解配置、XML配置和Java配置。

  • 注解配置:如果使用@Component注解,Spring会自动检测并注册BeanPostProcessor:
java">@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    // 方法实现如上
}
  • XML配置:在XML文件中显式声明BeanPostProcessor:
<bean class="com.example.CustomBeanPostProcessor" />
  • Java配置:通过@Bean注解注册BeanPostProcessor:
java">@Configuration
public class AppConfig {
    @Bean
    public BeanPostProcessor customBeanPostProcessor() {
        return new CustomBeanPostProcessor();
    }
}
5. BeanPostProcessor的工程化应用

BeanPostProcessor在工程化应用中具有重要意义。通过在Bean的生命周期中插入定制化逻辑,开发者可以实现许多高级功能,例如:

  • AOP(面向切面编程):通过代理技术,在Bean的方法调用前后添加额外逻辑,例如日志记录、事务管理、安全检查等。
  • 依赖注入的增强:在Bean初始化前后对其依赖进行进一步的配置和优化,例如动态注入特定依赖。
  • Bean管理:在Bean的整个生命周期中,进行统一的管理和监控,例如资源的初始化和释放、性能监控等。
6. 深入理解BeanPostProcessor的工作机制

为了更好地理解BeanPostProcessor的工作机制,我们需要了解Spring容器的初始化过程。Spring容器在启动时,会进行以下几个主要步骤:

  1. 实例化Bean:Spring容器根据配置文件或注解,实例化所有的Bean。
  2. 属性注入:为每个Bean注入其依赖的属性,这些属性可以是其他Bean、基本类型、集合等。
  3. 调用BeanPostProcessor:在Bean初始化前后,调用所有注册的BeanPostProcessor的方法。
  4. 调用初始化方法:如果Bean实现了InitializingBean接口,调用其afterPropertiesSet方法;如果配置了init-method,则调用该方法。
  5. Bean就绪:Bean已经准备好,可以被应用程序使用。

在这个过程中,BeanPostProcessor的两个方法分别在第3步和第4步之间被调用,允许开发者在Bean的生命周期的关键节点进行干预和自定义操作。

7. 实践中的BeanPostProcessor应用

在实际开发中,BeanPostProcessor的应用非常广泛,下面列举几个常见的使用场景:

  • 自定义初始化逻辑:通过在postProcessBeforeInitialization方法中添加逻辑,可以在Bean初始化之前执行一些自定义操作。例如,为Bean的某些属性设置默认值,或进行特定的初始化操作。
  • 动态代理:在postProcessAfterInitialization方法中,可以使用JDK动态代理或CGLIB代理,为Bean添加AOP增强。例如,为某些方法添加事务管理、日志记录或安全检查。
  • 注解处理:通过在Bean初始化前后扫描特定注解,可以实现注解驱动的配置。例如,自定义注解用于标记需要进行特定处理的Bean,并在BeanPostProcessor中实现相应的逻辑。
8. BeanPostProcessor与其他Spring机制的结合

BeanPostProcessor常常与Spring的其他机制结合使用,以实现更复杂和强大的功能。例如:

  • BeanFactoryPostProcessor结合BeanFactoryPostProcessor允许在Bean定义加载后、Bean实例化前进行配置修改。通过结合使用这两个接口,可以在Bean定义和实例化的不同阶段进行干预,提供更细粒度的控制。
  • ApplicationContextAware结合:实现ApplicationContextAware接口的Bean可以获取到ApplicationContext实例,通过在BeanPostProcessor中对这些Bean进行处理,可以实现对整个应用上下文的操作。
  • @PostConstruct@PreDestroy结合:在Bean的生命周期中,通过BeanPostProcessor和这两个注解,可以实现复杂的初始化和销毁逻辑。例如,在Bean初始化后,调用特定方法进行资源的分配或初始化。
9. 高级使用技巧

在高级使用场景中,BeanPostProcessor可以用于实现更复杂的功能,例如:

  • 多层次代理:通过在postProcessAfterInitialization方法中多次对Bean进行代理,可以实现多层次的功能增强。例如,先添加事务管理,再添加日志记录。
  • 条件处理:在BeanPostProcessor中,可以根据特定条件对Bean进行不同的处理。例如,根据Bean的类型或注解,选择性地进行某些操作。
  • 性能优化:通过在Bean初始化前后进行性能监控,可以识别出性能瓶颈,并采取相应的优化措施。例如,记录Bean初始化的时间,找出耗时较长的操作。

BeanPostProcessor源码跟踪

refresh方法中的registerBeanPostProcessors

java">@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing. 1、初始化上下文信息,替换占位符、必要参数的校验
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory. 2、解析类Xml、初始化BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计
			// Prepare the bean factory for use in this context. 	3、准备BeanFactory内容:
			prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展:
			try {
				// Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context. 	5、spring bean容器的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation. 	6、注册bean的后置处理器
				//!!!!!!!!!!!!  这里 这里 今天看这里  !!!!!!!!!!!//
				registerBeanPostProcessors(beanFactory);
				//!!!!!!!!!!!!  这里 这里 今天看这里  !!!!!!!!!!!//

				// Initialize message source for this context.	7、初始化消息源
				initMessageSource();
				// Initialize event multicaster for this context.	8、初始化事件广播器
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展
				onRefresh();
				// Check for listener beans and register them.	10、初始化监听器
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.	11、实例化:非兰加载Bean
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.	 12、发布相应的事件通知
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

java">
	/**
	 * Instantiate and register all BeanPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before any instantiation of application beans.
	 */
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

registerBeanPostProcessors详解

java">	/**
	 *
	 * @param beanFactory
	 * @param applicationContext
	 */
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// 1、获取所有实现BeanPostProcessor接口的类
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when a bean is created during BeanPostProcessor instantiation, i.e. when a bean is not eligible for getting processed by all BeanPostProcessors.
		// 记录下BeanPostProcessor的目标计数
		// +1是因为在此方法的最后会添加一个BeanPostProcessorChecker的类
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		// 2、添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		// 3、初始化根据BeanPostProcessor是否实现Priority、Order接口进行分类,初始化各种类型的集合,分类装这些对象
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// Spring自己内部的Bean后置处理器
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 4、遍历步骤一中所有后置处理器的名称
		for (String ppName : postProcessorNames) {
			// 实现PriorityOrdered类型的Bean
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				//  实现PriorityOrdered同时也实现类MergedBeanDefinitionPostProcessor接口,
				//  那么对应的bean实例添加到internalPostProcessors中,与实例化相关注解如@Autowired @Bean等关系密切,需要注意
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			// 实现Ordered类型的Bean
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		// 5、将实现类PriorityOrder接口类型的bean先注入到BeanFactory中
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 6、将实现类Order接口类型的bean先注入到BeanFactory中
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 6、将实现类Order接口类型的bean先注入到BeanFactory中
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 7.将无序普通的bean后处理器,注册到容器beanFactory中
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		// 8、最后,将Spring容器内部的BeanPostProcessor注册到Bean后置处理器中
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

代码解析与重点总结
1. 获取所有实现BeanPostProcessor接口的类
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

此步骤从BeanFactory中获取所有实现了BeanPostProcessor接口的Bean名称。这是为了后续将这些Bean按照不同的规则进行处理和注册。

2. 添加BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

BeanPostProcessorChecker的作用是记录信息,当在BeanPostProcessor实例化过程中创建一个Bean时,它会输出一条信息日志。这一步是为了确保在BeanPostProcessor注册过程中Bean创建的可追溯性。

3. 根据类型分类BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        priorityOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        orderedPostProcessorNames.add(ppName);
    } else {
        nonOrderedPostProcessorNames.add(ppName);
    }
}

在这一步,所有的BeanPostProcessor根据是否实现了PriorityOrdered、Ordered接口进行分类,分别放入不同的列表中。这是为了后续按照优先级进行注册。

4. 按优先级顺序注册BeanPostProcessor
// 注册实现PriorityOrdered接口的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// 注册实现Ordered接口的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    orderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
    }
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// 注册普通的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    nonOrderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
    }
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

按照实现PriorityOrdered、Ordered接口以及普通BeanPostProcessor的顺序,分别注册这些BeanPostProcessor。这确保了不同优先级的BeanPostProcessor按正确的顺序执行。

5. 注册内部BeanPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

将Spring内部使用的BeanPostProcessor(实现MergedBeanDefinitionPostProcessor接口的)单独处理并注册。这些内部BeanPostProcessor与Bean的实例化相关注解(如@Autowired、@Bean)关系密切,需要特别注意。

6. 添加ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

最后,添加一个ApplicationListenerDetector,用于检测内部Bean是否作为ApplicationListeners(应用监听器),并将其移动到处理链的末尾,以便捕获代理等操作。

小结

BeanPostProcessor是Spring框架提供的一个强大工具,它允许我们开发者在Bean的生命周期中的特定点进行自定义操作。通过实现BeanPostProcessor接口,开发者可以插入自己的逻辑,以增强或修改Bean的行为。这个接口在AOP、依赖注入和Bean管理等方面都有着广泛的应用。正确地使用BeanPostProcessor可以极大地提高Spring应用的灵活性和可扩展性。

通过本文的详细介绍,相信大家对BeanPostProcessor有了更深入的理解。在实际开发中,合理地应用BeanPostProcessor,可以帮助我们更好地控制和管理Bean的生命周期,实现复杂的业务需求。

整体总结


http://www.niftyadmin.cn/n/5537173.html

相关文章

加速度传感器信号处理注意事项

1 传感器分类 对于压电式压力传感器而言&#xff0c;输出信号是最重要的选择标准之一。压电式压力传感器与电子电路相连&#xff0c;电子电路将传感器产生的电荷成比例转换为电压。 如果选用外部设备&#xff08;电荷放大器&#xff09;充当电子元件&#xff0c;则称其为电…

【vue】JSON数据导出excel

前言 导出方式有很多种&#xff0c;但是若只需要数据导出成.xlsx文件并下载的话&#xff0c;只用xlsx一个插件就行 目标 1 实现数据导出excel 2 如何设置表格列宽 3 如何在文件中创建工作表 准备工作 1 安装 npm i xlsx -S 2 引入 npm i xlsx -S 二、导出excel 创建文件 con…

如何计算弧线弹道的落地位置

1&#xff09;如何计算弧线弹道的落地位置 2&#xff09;Unity 2021 IL2CPP下使用Protobuf-net序列化报异常 3&#xff09;编译问题&#xff0c;用Mono可以&#xff0c;但用IL2CPP就报错 4&#xff09;Wwise的Bank在安卓上LoadBank之后&#xff0c;播放没有声音 这是第393篇UWA…

上海市计算机学会竞赛平台2023年2月月赛丙组平分数字(一)

题目描述 给定 &#x1d45b;n 个整数&#xff1a;&#x1d44e;1,&#x1d44e;2,⋯ ,&#x1d44e;&#x1d45b;a1​,a2​,⋯,an​&#xff0c;请判定能否将它们分成两个部分&#xff08;不得丢弃任何数字&#xff09;&#xff0c;每部分的数字之和一样大。 输入格式 第…

IPsec连接 和 SSL连接

Psec和SSL连接是两种用于保障网络通信安全的技术 IPsec 通常用于连通两个局域网&#xff0c;主要是网对网的连接&#xff0c;如分支机构与总部之间&#xff0c;或者本地IDC与云端VPC的子网连接。适合站点间的稳定通讯需求以及对网络层安全有严格要求的场合。要求两端有固定的网…

chrome浏览器打开控制台很慢解决办法

问题&#xff1a;谷歌浏览器右键或者f12打开控制台速度很慢&#xff0c;需要等个几秒 解决&#xff1a; 设置成english(us)即可

期末C语言易错知识点整理

1.在定义多维数组时&#xff0c;除了最左边的维度&#xff0c;其余的维度必须明确指定大小 2.int m[1][4]{4}; 定义的是一个 1 行 4 列的二维数组&#xff0c;初始化时提供了一个元素 4&#xff0c;其余元素默认初始化为 0&#xff0c;因此是正确的。 3.二维数组 a[3][6] 中的索…

Python | Leetcode Python题解之第213题打家劫舍II

题目&#xff1a; 题解&#xff1a; class Solution:def rob(self, nums: List[int]) -> int:def robRange(start: int, end: int) -> int:first nums[start]second max(nums[start], nums[start 1])for i in range(start 2, end 1):first, second second, max(fi…