Spring 源码梳理(四) BeanFactoryPostProcessor

原创 2016年08月30日 13:52:24

BeanFactoryPostProcessor

上篇介绍了BeanPostProcessor(后面以Post代替),这篇讲的是BeanFactoryPostProcessor(后面以PostFactory代替),后者也是可以修改Bean的配置。 

1.它们的区别是什么?不是网上说的“BeanPostProcessor不能够修改Bean的配置,而BeanFactoryPostProcessor可以”,实际上两者都是可以,它们的区别实际上是,对Bean的修改的“层面”不同;

做一个这样的比喻,类Bean是一个模具,实例化后的bean是从模具中出来的模型,PostFactory是作用是修改这个模具,而Post作用是修改放入模具中的产品的原料以及修改从模具中出来的产品的原料。 整个过程就是这样的,Spring找到Bean模具,PostFactory修改模具,Post先改变原料,然后放入Bean这个模具,产品出来后Post再次修改这个产品。

2.PostFactory如何使用?

我们看一下源代码:


PostProcessor的注册位于Bean的加载之后和Post的注册之前;进入到这个invokeBeanFactoryPostProcessors的内部:


上面的第一个方法getBeanNamesForType查找所有实现BeanFactoryPostProcessor的类,然后通过add方法把这些类加入到无序的List中(其中也有有序List),说明支持BeanFactoryPostProcessor的排序。最后invokeBeanFactoryPostProcessors方法真正执行所有的实现类(nonOrderedPostProcessors);下面实例演示它的用法。

3.在演示之前,对于Post除了前面文章的讲述外,还有一个细节:继续上一篇文章,我们仍然分析下面这个方法doCreateBean


上图两个方法都是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory中的doCreateBean方法中的,第一个方法执行构造函数,第二个方法如下:


4.到此为止,执行顺序全部清楚了,下面贴上实例:

App.java

package com.mycompany.app;

import org.springframework.beans.factory.InitializingBean;

public class App implements InitializingBean
{
	private App(){
		System.out.println("App.App()");
	}
	private  String says="App";
    public String getSays() {
		return says;
	}
	public void setSays(String says) {
		this.says = says;
	}
	public void say(){
    	System.out.println("App.app():"+says);
    }
	
	/**
	 * 在构造函数和getset方法之后执行postProcessBeforeInitialization方法
	 */
	
	/*这个方法是InitializingBean在继承InitializingBean接口后,要实现的方法,顾名思义,是在
	 *属性设置之后进行一些操作*/
	public void afterPropertiesSet() throws Exception {
		System.out.println("App.afterPropertiesSet()");
	}
	/*这个方法是在Spring配置中通过init-method属性指定为该方法,然后才会执行,在afterPropertiesSet方法之后*/
	public void initMethod(){
		System.out.println("App.initMethod()");
	}
	
	/**
	 *在afterPropertiesSet和initMethod方法之后执行postProcessAfterInitialization方法
	 */
	
}

BeanPostProcessorApp.java

package com.mycompany.app;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class BeanPostProcessorApp implements BeanPostProcessor{
	
	/*如果打印结果出现该字符串,证明进行了初始化*/
	private BeanPostProcessorApp(){
		System.out.println("BeanPostProcessorApp.BeanPostProcessorApp()");
	}
	
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		if(bean instanceof App){
			((App)bean).setSays("Before:BeanPostProcessorApp");
			System.out
					.println("BeanPostProcessorApp.postProcessBeforeInitialization()");
		}
		return bean;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		if(bean instanceof App){
			((App)bean).setSays("After:BeanPostProcessorApp");
			System.out
					.println("BeanPostProcessorApp.postProcessAfterInitialization()");
		}
		return bean;
	}

}

BeanFactoryPostProcessorApp.java

package com.mycompany.app;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class BeanFactoryPostProcessorApp implements BeanFactoryPostProcessor{
	private BeanFactoryPostProcessorApp() {
		System.out.println("BeanFactoryPostProcessorApp.BeanFactoryPostProcessorApp()");
	}

	public void postProcessBeanFactory(
			ConfigurableListableBeanFactory beanFactory) throws BeansException {
		BeanDefinition beanDefinition = (BeanDefinition)beanFactory.getBeanDefinition("app");
		beanDefinition.setAttribute("says", "BeanFactoryPostProcessor");
		System.out
				.println("BeanFactoryPostProcessorApp.postProcessBeanFactory(): "+beanDefinition.getAttribute("says"));
	}

}

SpringBean.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
   
      
    <bean id="app" class="com.mycompany.app.App" init-method="initMethod"></bean>  
  
  	<bean id="beanPostProcessorApp" class="com.mycompany.app.BeanPostProcessorApp"></bean>
  	
  	<bean id="beanFactoryPostProcessorApp" class="com.mycompany.app.BeanFactoryPostProcessorApp"></bean>
</beans>

BeanFactoryPostProcessorAppTest.java

package com.mycompany.app;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactoryPostProcessorAppTest {
	public static void main(String[] args) {
    	@SuppressWarnings("resource")
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringBean.xml"); 
        App app = (App)applicationContext.getBean("app");  
        app.say();
	}

}

整体目录如下(AppTest...等三个文件,内容其实是一样的):


运行BeanFactoryPostProcessorAppTest.java,结果如下,和上面的分析是一致的:


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析

首先下面是我的Bean /* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apach...

Spring中BeanPostProcessor和BeanFactoryPostProcessor对比

Spring中BeanPostProcessor和BeanFactoryPostProcessor对比

Spring的后置处理器(BeanFactoryPostProcessor和BeanPostProcessor)

主要区别就是: BeanFactoryPostProcessor可以修改BEAN的配置信息而BeanPostProcessor不能,下面举个例子说明 BEAN类:   package com.sp...

spring 后置处理器BeanFactoryPostProcessor和BeanPostProcessor的用法和区别

出处:http://blog.csdn.net/xiao_jun_0820/article/details/7242379 主要区别就是: BeanFactoryPostProcessor可...

【Spring学习24】容器扩展点:后置处理器BeanFactoryPostProcessor

上篇说到的BeanPostProcessor(Bean后置处理器)常用在对bean内部的值进行修改;实现Bean的动态代理等。 BeanFactoryPostProcessor和BeanPostPr...
  • soonfly
  • soonfly
  • 2017年04月06日 21:34
  • 480

Spring BeanFactoryPostProcessor Bean后处理器 执行时机

上图是BeanPostProcessor 的两个接口的调用时机 下面我们来分析一下通过BeanFactory作为容器实例化bean及bean后处理器的执行时机: bean调用相应的构造函数,一般是空...

Spring 源码梳理(一) ClassPathXmlApplicationContext

1.为什么要分析Spring源码: 1)有意往架构上发展,分析Spring可清楚它做了哪些事情,如何做这些事情 2)Spring本身是对Java的丰富和发展,阅读可提高自己的水平 2.怎样分析Spri...

Spring 源码梳理(六) BeanNameAware和BeanFactoryAware

BeanNameAware和BeanFactoryAware 1.BeanNameAware和BeanFactoryAware概念 BeanNameAware:实现该接口的Bean能够在初始化时知道自...

Spring 源码梳理(九) AOP与动态代理

SpringAOP的核心是动态代理,就从动态代理开始分析,然后就会谈到静态代理,以及为什么会有代理这个说法,后面逐一分析: 1.什么是代理,为什么会有代理? 类甲的代理就是代替甲来完成甲的功能,比如实...

spring源码深度解析(笔记四)--bean的加载

分析: BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); MyTestBean...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring 源码梳理(四) BeanFactoryPostProcessor
举报原因:
原因补充:

(最多只允许输入30个字)