前言
开心一刻
小明:"妈, 我被公司开除了", 妈:"啊, 为什么呀?", 小明:"我骂董事长是笨蛋, 公司召开高层会议还要起诉我", 妈:"告你诽谤是吧?", 小明:"不是, 他们说要告我泄露公司机密"
BeanPostProcessor 定义
不管三七二十一, 我们先来看看它的定义, 看看 spring 是如何描述 BeanPostProcessor 的
- /*
- * Copyright 2002-2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.beans.factory.config;
- import org.springframework.beans.BeansException;
- import org.springframework.lang.Nullable;
- /**
- * 允许对新的 bean 示例进行自定义的修改, 例如检查标志接口或进行代理封装
- *
- * spring 上下文会在它的 beng 定义中自动检测 BeanPostProcessor 实例, 并将它们应用于随后创建的每一个 bean 实例
- *
- * implement {@link #postProcessAfterInitialization}.
- * 通常, 通过实现 BeanPostProcessor 的 postProcessBeforeInitialization 方法 (配合标记接口, 如 @Autowired) 来填充 bean 实例,
- * 通过 BeanPostProcessor 的 postProcessAfterInitialization 方法进行 bean 实例的代理
- *
- */
- public interface BeanPostProcessor {
- /**
- * 在 bean 实例的初始化方法 (例如 InitializingBean 的 afterPropertiesSet 或自定义的 init-method) 回调之前,
- * spring 会应用此方法到 bean 实例上. 一般用于 bean 实例的属性值的填充
- * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
- * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * <p>The default implementation returns the given {@code bean} as-is.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one;
- * if {@code null}, no subsequent BeanPostProcessors will be invoked
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- */
- @Nullable
- default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- /**
- * 在 bean 实例的初始化方法 (例如 InitializingBean 的 afterPropertiesSet 或自定义的 init-method) 回调之后,
- * spring 会应用此方法到 bean 实例上.
- * 在有 FactoryBean 时, 此方法会在 FactoryBean 实例与 FactoryBean 的目标对象创建时各调用一次
- * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
- * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
- * instance and the objects created by the FactoryBean (as of Spring 2.0). The
- * post-processor can decide whether to apply to either the FactoryBean or created
- * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
- * <p>This callback will also be invoked after a short-circuiting triggered by a
- * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
- * in contrast to all other BeanPostProcessor callbacks.
- * <p>The default implementation returns the given {@code bean} as-is.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one;
- * if {@code null}, no subsequent BeanPostProcessors will be invoked
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- * @see org.springframework.beans.factory.FactoryBean
- */
- @Nullable
- default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- }
- View Code
简单点来理解, 就是 spring 会自动从它的所有的 bean 定义中检测 BeanPostProcessor 类型的 bean 定义, 然后实例化它们, 再将它们应用于随后创建的每一个 bean 实例, 在 bean 实例的初始化方法回调之前调用 BeanPostProcessor 的 postProcessBeforeInitialization 的方法(进行 bean 实例属性的填充), 在 bean 实例的初始化方法回调之后调用 BeanPostProcessor 的 postProcessAfterInitialization 的方法(可以进行 bean 实例的代理封装)
应用示例
我们先来看个简单的示例, 注意: 由于 spring 只是从 spring 容器中的 bean 定义中自动检测 BeanPostProcessor 类型的 bean 定义, 所以我们自定义的 BeanPostProcessor 要通过某种方式注册到 spring 容器
MyBeanPostProcessor
- @Component
- public class MyBeanPostProcessor implements BeanPostProcessor {
- public MyBeanPostProcessor () {
- System.out.println("MyBeanPostProcessor 实例化......");
- }
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("spring 中 bean 实例:" + beanName + "初始化之前处理......");
- return bean;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("spring 中 bean 实例:" + beanName + "初始化之后处理......");
- return bean;
- }
- }
- View Code
- AnimalConfig
- @Configuration
- public class AnimalConfig {
- public AnimalConfig() {
- System.out.println("AnimalConfig 实例化");
- }
- @Bean
- public Dog dog() {
- return new Dog();
- }
- }
- View Code
- Dog
- public class Dog {
- private String name;
- public Dog() {
- System.out.println("Dog 实例化......");
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- View Code
完整实例工程: spring-boot-BeanPostProcessor 我们来看看启动结果
有人可能会说了:"你是个逗比把, 你举的这个例子有什么用? 实际上, 根本就不会出现 BeanPostProcessor 的这样用法!" 有这样的疑问非常正常, 示例中的 BeanPostProcessor 的两个方法: postProcessBeforeInitialization,postProcessAfterInitialization 没做任何的处理, 都只是直接返回 bean, 这不就是: 脱了裤子放屁?
我们细看下, 会发现 postProcessBeforeInitialization,postProcessAfterInitialization 中各多了一行打印(), 其实示例只是验证下 Spring 对 BeanPostProcessor 的支持, BeanPostProcessor 的两个方法的执行时机, 是否如 BeanPostProcessor 的注释所说的那样, 实际应用中肯定不会这么用的. 那问题来了: BeanPostProcessor 能用来干什么? 回答这个问题之前, 我们先来看看 spring 对 BeanPostProcessor 的底层支持
源码解析
BeanPostProcessor 的实例化与注册
很明显, 我们从 spring 的启动过程的 refresh 方法开始, 如下图
此时 spring 容器中所有的 BeanPostProcessor 都进行了实例化, 并注册到了 beanFactory 的 beanPostProcessors 属性中
registerBeanPostProcessors
- public static void registerBeanPostProcessors(
- ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
- 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.
- int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
- beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
- // Separate between BeanPostProcessors that implement PriorityOrdered,
- // Ordered, and the REST.
- // 将所有 BeanPostProcessor bean 定义分三类: 实现了 PriorityOrdered, 实现了 Ordered, 以及剩下的常规 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)) {
- // 实例化实现了 PriorityOrdered 接口的 BeanPostProcessor
- 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);
- }
- }
- // First, register the BeanPostProcessors that implement PriorityOrdered.
- // 注册实现了 PriorityOrdered 接口的 BeanPostProcessor 到 beanFactory 的 beanPostProcessors 属性中
- sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
- registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
- // Next, register the BeanPostProcessors that implement Ordered.
- List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
- for (String ppName : orderedPostProcessorNames) {
- // 实例化实现了 Ordered 接口的 BeanPostProcessor
- BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
- orderedPostProcessors.add(pp);
- if (pp instanceof MergedBeanDefinitionPostProcessor) {
- internalPostProcessors.add(pp);
- }
- }
- // 注册实现了 Ordered 接口的 BeanPostProcessor 到 beanFactory 的 beanPostProcessors 属性中
- sortPostProcessors(orderedPostProcessors, beanFactory);
- registerBeanPostProcessors(beanFactory, orderedPostProcessors);
- // Now, register all regular BeanPostProcessors.
- List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
- for (String ppName : nonOrderedPostProcessorNames) {
- // 实例化剩下的所有的常规的 BeanPostProcessors
- BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
- nonOrderedPostProcessors.add(pp);
- if (pp instanceof MergedBeanDefinitionPostProcessor) {
- internalPostProcessors.add(pp);
- }
- }
- registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
- // Finally, re-register all internal BeanPostProcessors.
- // 注册所有常规的的 BeanPostProcessor 到 beanFactory 的 beanPostProcessors 属性中
- 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));
- }
- View Code
BeanPostProcessor 的生效时机
前面我们已经知道, spring 会应用 BeanPostProcessor 于随后创建的每一个 bean 实例, 具体 spring 是如何做到的了, 我们仔细来看看
finishBeanFactoryInitialization 方法实例化所有剩余的, 非延迟初始化的单例(默认情况下 spring 的 bean 都是非延迟初始化单例), 具体如下
BeanPostProcessor 应用场景
其实只要我们弄清楚了 BeanPostProcessor 的执行时机: 在 bean 实例化之后, 初始化前后被执行, 允许我们对 bean 实例进行自定义的修改; 只要我们明白了这个时机点, 我们就能分辨出 BeanPostProcessor 适用于哪些需求场景, 哪些需求场景可以用 BeanPostProcessor 来实现
spring 中有很多 BeanPostProcessor 的实现, 我们接触的比较多的自动装配: AutowiredAnnotationBeanPostProcessor 也是 BeanPostProcessor 的实现之一, 关于自动装配我会在下篇博文中与大家一起探索
总结
spring 中 bean 的生命周期如下图
引用自: Spring 实战系列(三)-BeanPostProcessor 的妙用
来源: https://www.cnblogs.com/youzhibing/p/10559330.html