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 源码梳理(四) BeanFactoryPostProcessor

BeanFactoryPostProcessor 上篇介绍了BeanPostProcessor(后面以Post代替),这篇讲的是BeanFactoryPostProcessor(后面以PostFac...

Spring 源码梳理(二) BeanPostProcessor

BeanPostProcessor 1.BeanPostProcessor的概念 BeanPostProcessor是一个接口,它可以使得继承它的类成为一个"回调类"(自己起的称呼),继承的方法成为...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Spring 源码梳理(一) ClassPathXmlApplicationContext

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

Spring 源码梳理(七) 注解源码

1.Spring的注解可以分为两类,一个是类上的注解,如@Component; 一个是类内部的注解,如@Autowired;Spring对两种形式的注解的处理是不同的,在Spring的初始化周期中注解...

Android 源码梳理

Android 源码梳理 前言 作为霜枫司机一年学习的总结,附上帅照一张。 目录 1. Android系统启动过程分析 2. Android进程间通信源码梳理 3. And...

Spring 源码梳理(五) FactoryBean与BeanFactory

1.什么是FactoryBean,,后缀是'Bean'证明本质上仍然是一个Bean,仍然要放入BeanFactory中,只是它实现了FactoryBean接口; 2.特点:根据该Bean的id从Bea...

Spring 源码梳理(三) 再谈BeanPostProcessor

再谈BeanPostProcessor 上篇文章介绍的是BeanPostProcessor的用法,在最后留下了一个问题,对于Spring中的Bean属性'Lazy-init'(延迟加载),当Hook...

Spring 源码梳理(六) BeanNameAware和BeanFactoryAware

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

Dubbo源码梳理

Dubbo提供者初始化过程分析 Dubbo解析xml,初始化且暴露所有服务 由服务配置类ServiceConfig进行初始化工作及服务暴露入口 ServiceConfig.export(); ...

ButterKnife源码梳理

写代码的时候,总会要不厌其烦的写findViewById,butterknife这个框架的作用就是利用注解来简化view查找过程。 先了解下注解的几个关键词: Target:限定使用范围 ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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