BeanPostProcessor是使用IoC容器时经常使用会遇到的一个特性,这个Bean的后置处理器是一个监听器,它可以监听容器触发的事件。把它向IoC容器注册以后,使得容器中管理的Bean具备接收IoC 容器事件回调的能力。具体的后置处理器需要实现接口BeanPostProcessor,然后设置到XML的Bean的配置文件中。这个BeanPostProcessor是一个接口类,它有两个接口方法,一个是Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;,为在Bean 的初始化前提供回调入口。另一个:Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;,为在Bean的初始化以后提供回调入口,这两个回调的触发都是和容器管理Bean的生命周期相关。
AbstractAutowireCapableBeanFactory的doCreateBean方法中
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
在对Bead的生成和依赖注入完成后,开始对bean进行初始化,这个初始化过程包含了对后置处理器的调用
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
具体的初始化过程也是依赖注入的一个重要部分。在initializeBean方法里,需要Bean的名字,完成依赖注入以后的bean对象,以及这个Bean对应的Beandefinition。在这些输入的帮助下完成Bean的初始化的工作,包括为类型是BeanNameAware的Bean设置Bean的名字,为类型BeanClassLoaderAware的Bean设置类装载器,为类型BeanFactoryAware的Bean设置其自身所在的IoC容器以供回调使用。这些实现在:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
中,接着是对后置处理器BeanPostProcessors的postProcessBeforeInitialization的回调方法的调用:
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
具体的实现过程见applyBeanPostProcessorsBeforeInitialization:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
调用Bean的初始化方法吗,这个初始化方法是在BeanDefinition中通过定义init-method属性指定的,同时如果Bean实现了InitializingBean接口,那么Bean的afterPropertiesSet的实现也会被调用。
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
具体的实现步骤如下:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
然后就是对后置处理器BeanPostProcessor的postProcessAfterInitialization的回调方法调用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
具体的实现步骤如下:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
由上面的源码分析可知:BeanPostProcessors的postProcessBeforeInitialization先于Bean的属性init-method中配置的方法或者是Bean继承的InitializingBean接口后实现afterPropertiesSet方法执行。接着继续执行BeanPostProcessors的postProcessAfterInitialization方法。
分享到:
相关推荐
### Spring源码解析:从IOC创建到Bean的注册 #### 概述 Spring框架作为Java领域内最流行的轻量级框架之一,其核心是依赖注入(Dependency Injection, DI)和面向切面编程(Aspect Oriented Programming, AOP)。在...
### Spring源码解析知识点 #### 1. Spring IoC 容器概述 Spring 框架的核心特性之一是它的依赖注入(Dependency Injection, DI)能力,这种能力通过一个称为 Inversion of Control (IoC) 容器来实现。IoC 容器负责...
同时,了解Spring源码也有助于开发者更好地选择和集成其他Java库,提升开发效率和应用性能。 总结来说,Spring源代码解析涵盖了IoC容器的运作、AOP的实现、数据访问的策略以及Web MVC的流程。深入研究这些内容,将...
通过对Spring源码的深入分析,我们可以了解到Spring是如何实现这些功能的,这将有助于我们在开发过程中更好地利用Spring,解决实际问题,提升系统性能。同时,源码阅读也能锻炼我们的设计思维和编程能力,让我们能站...
### Spring源码refresh方法调试笔记 #### 一、概述 `refresh` 方法是Spring框架中的一个核心方法,它主要用于初始化整个应用上下文(ApplicationContext),包括加载配置文件、创建Bean实例等重要步骤。本文将深入...
Spring源码流程图解析 Spring源码流程图是了解Spring框架核心组件和Bean生命周期的关键。下面我们将深入探讨Spring源码流程图,了解核心组件、Bean定义信息、Bean工厂、Bean生命周期和Aware接口的作用。 核心组件...
5. **搭建Spring源码阅读环境** - 从GitHub下载Spring框架的源码。 - 安装和配置 `gradle`、Idea等开发工具。 - 根据Spring的模块结构编译源码,通常需要按照 `core-oxm-context-beans-aspects-aop` 的顺序进行。...
通过实现`BeanFactoryPostProcessor`或`BeanPostProcessor`接口,你可以扩展Spring的行为,使其在处理自定义注解时执行特定的操作。 总结来说,Spring中注解的实现原理涉及到元注解的定义、注解处理器的运行、Bean...
《Spring框架4.3源码解析》 Spring框架作为Java领域中最广泛应用的开源框架之一,其设计理念、设计模式以及核心组件的实现一直是开发者们深入学习的重点。4.3版本是Spring发展过程中的一个重要里程碑,它引入了许多...
"Spring源码分析" 在 Spring 框架中,Bean 对象的创建过程是一个复杂的过程,涉及到多个步骤和接口。下面将对 Spring 源码中 Bean 对象的创建过程进行分析和解释。 1. 创建工厂,到达 BeanDefinition 步骤 在 ...
以下是对 Spring 源码中关键知识点的详细解析: 1. **依赖注入(Dependency Injection, DI)**:Spring 的核心特性之一,它允许开发者通过配置文件或注解来管理对象间的依赖关系,降低耦合度。在源码中,我们可以...
本篇文章将深入探讨Spring依赖注入的实现原理,以及如何通过源码理解和使用这一特性。 一、依赖注入简介 依赖注入的基本思想是,对象不应该负责创建或查找它所依赖的对象,而应该由外部容器(如Spring框架)来负责...
源码解析部分通常会详细解释Spring的各个组件和模块是如何协同工作的。例如,解析`DefaultListableBeanFactory`如何根据XML或Java配置来实例化和管理bean,`AbstractAopProxy`是如何创建代理对象以实现AOP功能,以及...
9. **Spring AOP实现**:Spring通过动态代理(JDK Proxy和CGLIB)实现AOP,这在源码中是重要部分,可以深入了解其底层工作原理。 通过阅读和分析Spring 2.5.4的源码,我们可以更好地理解Spring的内部机制,这对于...
通过对源码的学习,你可以了解到 Bean 的生命周期、AOP 切面的实现方式、MVC 框架的调度流程等细节,这对于深入理解 Spring 并且定制化开发非常有帮助。 在分析源码时,可以关注以下几个关键点: - 如何通过注解和 ...
《深入剖析Spring Beans源码》 Spring框架是Java开发中不可或缺的部分,其核心组件之一就是`spring-beans`模块。这个模块主要负责Spring容器的创建、管理Bean的生命周期以及依赖注入(Dependency Injection,简称DI...
在深入探讨Spring的XML解析原理之前,让我们先理解Spring框架的核心概念:控制反转(Inversion of Control...总的来说,理解Spring的XML解析原理有助于我们更好地利用Spring框架,同时也为深入学习Spring源码打下基础。
在源码中,你可以看到`DefaultListableBeanFactory`和`BeanDefinition`等类是如何协同工作来实现bean的实例化和依赖解析的。 3. **BeanDefinition**:这个接口及其实现类定义了如何创建一个bean,包括它的类、属性...
在源码中,我们可以看到`BeanFactory`和`ApplicationContext`等接口及其实现类如何通过XML、Java配置或者注解方式来解析和管理bean的生命周期。 2. **单例模式与bean管理** - Spring中的bean默认为单例模式,由`...