`
imaginecup
  • 浏览: 87386 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring源码解析 BeanPostProcessor的实现

阅读更多

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方法。

 

分享到:
评论
1 楼 xuhang1128 2013-08-23  
good    

相关推荐

    Spring源码解析文件说明

    ### Spring源码解析:从IOC创建到Bean的注册 #### 概述 Spring框架作为Java领域内最流行的轻量级框架之一,其核心是依赖注入(Dependency Injection, DI)和面向切面编程(Aspect Oriented Programming, AOP)。在...

    spring源码解析

    ### Spring源码解析知识点 #### 1. Spring IoC 容器概述 Spring 框架的核心特性之一是它的依赖注入(Dependency Injection, DI)能力,这种能力通过一个称为 Inversion of Control (IoC) 容器来实现。IoC 容器负责...

    Spring源代码解析

    同时,了解Spring源码也有助于开发者更好地选择和集成其他Java库,提升开发效率和应用性能。 总结来说,Spring源代码解析涵盖了IoC容器的运作、AOP的实现、数据访问的策略以及Web MVC的流程。深入研究这些内容,将...

    Spring源码分析.rar

    通过对Spring源码的深入分析,我们可以了解到Spring是如何实现这些功能的,这将有助于我们在开发过程中更好地利用Spring,解决实际问题,提升系统性能。同时,源码阅读也能锻炼我们的设计思维和编程能力,让我们能站...

    Spring源码refresh方法调试笔记

    ### Spring源码refresh方法调试笔记 #### 一、概述 `refresh` 方法是Spring框架中的一个核心方法,它主要用于初始化整个应用上下文(ApplicationContext),包括加载配置文件、创建Bean实例等重要步骤。本文将深入...

    Spring源码流程图

    Spring源码流程图解析 Spring源码流程图是了解Spring框架核心组件和Bean生命周期的关键。下面我们将深入探讨Spring源码流程图,了解核心组件、Bean定义信息、Bean工厂、Bean生命周期和Aware接口的作用。 核心组件...

    Spring IoC源码深度剖析开源架构源码2021.pdf

    5. **搭建Spring源码阅读环境** - 从GitHub下载Spring框架的源码。 - 安装和配置 `gradle`、Idea等开发工具。 - 根据Spring的模块结构编译源码,通常需要按照 `core-oxm-context-beans-aspects-aop` 的顺序进行。...

    spring中注解的实现原理

    通过实现`BeanFactoryPostProcessor`或`BeanPostProcessor`接口,你可以扩展Spring的行为,使其在处理自定义注解时执行特定的操作。 总结来说,Spring中注解的实现原理涉及到元注解的定义、注解处理器的运行、Bean...

    spring源码4.3

    《Spring框架4.3源码解析》 Spring框架作为Java领域中最广泛应用的开源框架之一,其设计理念、设计模式以及核心组件的实现一直是开发者们深入学习的重点。4.3版本是Spring发展过程中的一个重要里程碑,它引入了许多...

    Spring源码分析.docx

    "Spring源码分析" 在 Spring 框架中,Bean 对象的创建过程是一个复杂的过程,涉及到多个步骤和接口。下面将对 Spring 源码中 Bean 对象的创建过程进行分析和解释。 1. 创建工厂,到达 BeanDefinition 步骤 在 ...

    spring源码包-源码包源码包

    以下是对 Spring 源码中关键知识点的详细解析: 1. **依赖注入(Dependency Injection, DI)**:Spring 的核心特性之一,它允许开发者通过配置文件或注解来管理对象间的依赖关系,降低耦合度。在源码中,我们可以...

    spring依赖注入的实现原理

    本篇文章将深入探讨Spring依赖注入的实现原理,以及如何通过源码理解和使用这一特性。 一、依赖注入简介 依赖注入的基本思想是,对象不应该负责创建或查找它所依赖的对象,而应该由外部容器(如Spring框架)来负责...

    spring-framework-5.2.0.RELEASE-master.zip

    源码解析部分通常会详细解释Spring的各个组件和模块是如何协同工作的。例如,解析`DefaultListableBeanFactory`如何根据XML或Java配置来实例化和管理bean,`AbstractAopProxy`是如何创建代理对象以实现AOP功能,以及...

    Spring 源码 2 .5.4

    9. **Spring AOP实现**:Spring通过动态代理(JDK Proxy和CGLIB)实现AOP,这在源码中是重要部分,可以深入了解其底层工作原理。 通过阅读和分析Spring 2.5.4的源码,我们可以更好地理解Spring的内部机制,这对于...

    spring源码代码

    通过对源码的学习,你可以了解到 Bean 的生命周期、AOP 切面的实现方式、MVC 框架的调度流程等细节,这对于深入理解 Spring 并且定制化开发非常有帮助。 在分析源码时,可以关注以下几个关键点: - 如何通过注解和 ...

    spring-beans源码

    《深入剖析Spring Beans源码》 Spring框架是Java开发中不可或缺的部分,其核心组件之一就是`spring-beans`模块。这个模块主要负责Spring容器的创建、管理Bean的生命周期以及依赖注入(Dependency Injection,简称DI...

    这一次搞懂Spring的XML解析原理说明

    在深入探讨Spring的XML解析原理之前,让我们先理解Spring框架的核心概念:控制反转(Inversion of Control...总的来说,理解Spring的XML解析原理有助于我们更好地利用Spring框架,同时也为深入学习Spring源码打下基础。

    Spring核心源码

    在源码中,你可以看到`DefaultListableBeanFactory`和`BeanDefinition`等类是如何协同工作来实现bean的实例化和依赖解析的。 3. **BeanDefinition**:这个接口及其实现类定义了如何创建一个bean,包括它的类、属性...

    spring源码

    在源码中,我们可以看到`BeanFactory`和`ApplicationContext`等接口及其实现类如何通过XML、Java配置或者注解方式来解析和管理bean的生命周期。 2. **单例模式与bean管理** - Spring中的bean默认为单例模式,由`...

Global site tag (gtag.js) - Google Analytics