转自: http://blog.csdn.net/kkdelta/article/details/5488430

Spring在解析完配置文件后,会调用一些callback方法,使用Spring的开发者可以通过提供这些callback方法达到对Spring Container的扩展.
1.   通过实现BeanPostProcessor来完成对某些Bean的一些定制, BeanPostProcessor定义了两个方法, postProcessBeforeInitialization(Object bean, String beanName)和postProcessAfterInitialization(Object bean, String beanName)。 postProcessBeforeInitialization会在Spring对bean初始化完成之后 , 依赖注册(对property指定的成员变量完成了赋值)已经完成 , 但是Container还没有调用申明的initialization方法(如afterPropertiesSet, init-method)之前被调用.postProcessAfterInitialization会在在Container调用申明的initialization方法(如afterPropertiesSet)之后被调用.如果需要有多个实现了BeanPostProcessor的类,可以通过让其实现Ordered接口来控制这些类的callback被调用的顺序。这种bean的post-processor一般用来检查bean是否实现了某个接口 , 或者把bean包装成某个proxy,Spring的AOP某些框架类就是实现了BeanPostProcessor.

例:

public class MyBeanPostProcessor implements BeanPostProcessor,
InvocationHandler {
private Object proxyobj;
public MyBeanPostProcessor() {
}
public MyBeanPostProcessor(Object obj) {
proxyobj = obj;
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessBeforeInitialization Bean '" + beanName
+ "' created : " + bean.toString());
if (bean instanceof Intf) {
Class cls = bean.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls
.getInterfaces(), new MyBeanPostProcessor(bean));
} else {
return bean;
}
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessAfterInitialization Bean '" + beanName
+ "' created : " + bean.toString());
return bean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("proxy is " + proxy.getClass().getName());
System.out.println("before calling " + method); if (args != null) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i] + "");
}
}
Object o = method.invoke(proxyobj, args);
System.out.println("after calling " + method);
return o;
}
}
public interface Intf {
public String testFunc();
}
public class IntfBean implements Intf {
private String strVal = "default value";
@Override
public String testFunc() {
// TODO Auto-generated method stub
return strVal;
}
} <bean id="IntfBean" class="com.test.spring.extent.IntfBean" />
<bean class="com.test.spring.extent.MyBeanPostProcessor" />

注意这里实现BeanPostProcessor的类是针对Ioc容器里其他的bean调用这两个方法,不是针对BeanPostProcessor自身和其他BeanPostProcessor调用这两个方法, 如果在配置文件里就只有BeanPostProcessor本身, 没有其他的bean, 如只有<beanclass="com.test.spring.extent.MyBeanPostProcessor"/>配置,postProcessBeforeInitialization和postProcessAfterInitialization这两个方法是不会被调用的.BeanPostProcessor会在普通bean被初始化之前先被容器初始化.

调用代码:

Intf intfBean = (Intf) ctx.getBean("IntfBean");

System.out.println(intfBean.testFunc());

这样,MyBeanPostProcessor会把实现Intf接口的bean包装成一个proxy.

 

2. 通过实现BeanFactoryPostProcessor接口来操作配置文件,对配置的元数据进行特制。 Spring IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其它的bean之前读取配置元数据,并有可能修改它。Spring自身的PropertyPlaceholderConfigurer 就实现了这个接口 , 通过对XML配置文件中使用占位符 , PropertyPlaceholderConfigurer从别的property文件中读取值进行替换。

例子:从ext.properties读取值替换${TEST.PROP1},${TEST.PROP2}.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:conf/ext.properties" />
<property name="properties">
<value>TEST.PROP3=inside property</value>
</property>
</bean>
<bean id="PropReplaceBean" class="com.test.spring.extent.PropReplaceBean">
<property name="strVal" value="${TEST.PROP1}" />
<property name="intVal" value="${TEST.PROP2}" />
<property name="insideProp" value="${TEST.PROP3}" />
</bean>

通常比较有用的场景是数据库的url,用户名,密码的配置,还可以用来动态指定某个bean的类名,把XMl文件和property文件分开维护更容易。

<bean id="xxxBean" class="${com.xxx.class}"/>

自定义的BeanFactoryPostProcessor,通过实现Ordered接口可以改变被callback的顺序。 callback方法中的ConfigurableListableBeanFactory beanFactory提供了配置文件的元数据。(*碰到一个困惑的问题是: PropertyPlaceholderConfigurer的order是 Integer.MAX_VALUE,却发现它比自己定义的order 为-1的 processor先执行.)

<bean class="com.test.spring.extent.MyBeanFactoryPostProcessor" />
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
Ordered {
private int order = -1;
public void setOrder(int order) {
this.order = order;
}
public int getOrder() {
return this.order;
}
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory
.getBeanDefinition("PropReplaceBean");
MutablePropertyValues pvs = beanDefinition.getPropertyValues();
PropertyValue[] pvArray = pvs.getPropertyValues();
for (PropertyValue pv : pvArray) {
System.out.println(pv.getName() + " " + pv.getValue().getClass());
}
}
}

Spring检测到BeanPostProcessor和BeanFactoryPostProcessor后会由容器自动调用它们的callback方法,不用在代码里主动的去调用.

Spring Container的扩展点的更多相关文章

  1. Spring中的扩展点

    Spring作为一个常用的IOC框架,在设计上预留了很多的扩展点,很多第三方开源框架,包括Spring自身也是基于这些扩展点实现的,这很好的体现了对修改关闭.对扩展开放的原则.总的来说Spring的扩 ...

  2. spring源码-扩展点

    /** * @Author quan * @Date 2020/11/13 * 扩展原理 * BeanPostProcessor bean后置处理器,bean创建对象初始化前后进行拦截工作 * * * ...

  3. Spring扩展点-v5.3.9

    Spring 扩展点 **本人博客网站 **IT小神 www.itxiaoshen.com 官网地址****:https://spring.io/projects/spring-framework T ...

  4. Spring系列14:IoC容器的扩展点

    Spring系列14:IoC容器的扩展点 回顾 知识需要成体系地学习,本系列文章前后有关联,建议按照顺序阅读.上一篇我们详细介绍了Spring Bean的生命周期和丰富的扩展点,没有阅读的强烈建议先阅 ...

  5. 三万字盘点Spring/Boot的那些常用扩展点

    大家好,我是三友. Spring对于每个Java后端程序员来说肯定不陌生,日常开发和面试必备的.本文就来盘点Spring/SpringBoot常见的扩展点,同时也来看看常见的开源框架是如何基于这些扩展 ...

  6. Spring Boot 中如何使用 Dubbo Activate 扩展点

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 公司的核心竞争力在于创新 – <启示录> 』 继续上一篇:< Spri ...

  7. Spring源码系列 — BeanDefinition扩展点

    前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...

  8. Spring扩展点之Aware接口族

    引言 Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContex ...

  9. spring mvc 提供的几个常用的扩展点

    转载 :http://blog.csdn.net/gufachongyang02/article/details/43836105 这是spring3 mvc的核心流程图:   SpirngMVC的第 ...

随机推荐

  1. Storm-源码分析-Topology Submit-Nimbus-mk-assignments

    什么是"mk-assignment", 主要就是产生executor->node+port关系, 将executor分配到哪个node的哪个slot上(port代表slot, ...

  2. 剑指Offer——整数中1出现的次数(从1到n整数中1出现的次数)

    题目描述: 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了 ...

  3. 类似于xml的一种数据传输格式protobuf

    1.Protobuf 简介 Protocol Buffer是google 的一种数据交换的格式,已经在Github开源,目前最新版本是3.1.0.它独立于语言,独立于平台.google 提供了多种语言 ...

  4. 使用maven为web工程引入jstl包时报错了

    原pom文件: <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</a ...

  5. 【开发者笔记】按List中存放对象的某一字段计数的问题

    如题,假设有如下表t_info: name date info a 20127-12-20 xxxx描述 b 20127-12-20 yyyyy描述 c 20127-12-21 zzz描述 d 201 ...

  6. w命令

    命 令:w 功能说明:显示目前登入系统的用户信息. 语 法:w [-fhlsuV][用户名称] 补充说明:执行这项指令可得知目前登入系统的用户有那些人,以及他们正在执行的程序.单独执行w 指令会显示所 ...

  7. centos7部署PaaS平台环境(mesos+marathon)

    假如有5台主机可以使用,ip地址如下 规划(2master+3slave) master: 192.168.248.205 ---master1 192.168.248.206 ---master2 ...

  8. OS知识点总结

    转自:https://blog.csdn.net/csdn_chai/article/details/78002202 1.什么是操作系统? OS是用户与硬件之间的接口,管理计算机的软件和硬件资源. ...

  9. python字符串搜索

    python字符串字串查找 find和index方法 更多0 python 字符串 python 字符串查找有4个方法,1 find,2 index方法,3 rfind方法,4 rindex方法. 1 ...

  10. GIL用C语言解决

    执行一个单线程死循环程序,单核cpu占用直接100% while True: pass 执行一个双线程的死循环程序,cpu同样占用100% import threading #子线程死循环 def t ...