上一篇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接口定义了两个主要方法:
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初始化前后添加日志:
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Before Initialization: " + beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("After Initialization: " + beanName);return bean;}
}
在这个例子中,我们实现了BeanPostProcessor接口,并在postProcessBeforeInitialization
和postProcessAfterInitialization
方法中分别添加了日志输出。这使得每当一个Bean在初始化之前或之后,这两个方法都会被调用,并输出相应的日志信息。
4. BeanPostProcessor的注册
要使BeanPostProcessor生效,必须将其注册到Spring容器中。注册方式有多种,包括注解配置、XML配置和Java配置。
- 注解配置:如果使用
@Component
注解,Spring会自动检测并注册BeanPostProcessor:
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {// 方法实现如上
}
- XML配置:在XML文件中显式声明BeanPostProcessor:
<bean class="com.example.CustomBeanPostProcessor" />
- Java配置:通过
@Bean
注解注册BeanPostProcessor:
@Configuration
public class AppConfig {@Beanpublic BeanPostProcessor customBeanPostProcessor() {return new CustomBeanPostProcessor();}
}
5. BeanPostProcessor的工程化应用
BeanPostProcessor在工程化应用中具有重要意义。通过在Bean的生命周期中插入定制化逻辑,开发者可以实现许多高级功能,例如:
- AOP(面向切面编程):通过代理技术,在Bean的方法调用前后添加额外逻辑,例如日志记录、事务管理、安全检查等。
- 依赖注入的增强:在Bean初始化前后对其依赖进行进一步的配置和优化,例如动态注入特定依赖。
- Bean管理:在Bean的整个生命周期中,进行统一的管理和监控,例如资源的初始化和释放、性能监控等。
6. 深入理解BeanPostProcessor的工作机制
为了更好地理解BeanPostProcessor的工作机制,我们需要了解Spring容器的初始化过程。Spring容器在启动时,会进行以下几个主要步骤:
- 实例化Bean:Spring容器根据配置文件或注解,实例化所有的Bean。
- 属性注入:为每个Bean注入其依赖的属性,这些属性可以是其他Bean、基本类型、集合等。
- 调用BeanPostProcessor:在Bean初始化前后,调用所有注册的BeanPostProcessor的方法。
- 调用初始化方法:如果Bean实现了InitializingBean接口,调用其
afterPropertiesSet
方法;如果配置了init-method
,则调用该方法。 - 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
@Overridepublic 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、初始化BeanFactoryConfigurableListableBeanFactory 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、实例化:非兰加载BeanfinishBeanFactoryInitialization(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();}}}
/*** 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详解
/**** @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类型的Beanif (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类型的Beanelse 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的生命周期,实现复杂的业务需求。