转自: 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. Linux磁盘分区工具的使用

    ----------fdisk分区工具----------   一..下面来介绍fdisk分区工具的命令格式:    fdisk是传统的Linux硬盘分区工具,也是Linux系统中最常用的一种硬盘分区 ...

  2. Java 之设计模式(总述)

    1. 面向对象设计原则 单一职责原则: 一个类只负责一个功能领域中的相应职责 开闭原则: 软件实体应对扩展开放,而对修改关闭; 里氏代换原则: 所有引用基类对象的地方能够透明地使用其子类的对象; 依赖 ...

  3. VC2005 warning C4819 消除方法

    一. Warning C4819:The file contains a character that can ot be represented in the current code page(9 ...

  4. MySQL优化(二):SQL优化

    一.SQL优化 1.优化SQL一般步骤 1.1 查看SQL执行频率 SHOW STATUS LIKE 'Com_%'; Com_select:执行SELECT操作的次数,一次查询累加1.其他类似 以下 ...

  5. bug-sqlite3

    [root@izj6c6b4i40od17ev77lhez Python-3.7.0]# python Python 3.7.0 (default, Sep 5 2018, 00:40:27) [GC ...

  6. 搭建高性能Jboss负载均衡集群

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/a1314517love/article/details/26836357 负载均衡集群是由两台或者两 ...

  7. MongoDB学习笔记系列~目录

    MongoDB学习笔记~环境搭建 (2015-03-30 10:34) MongoDB学习笔记~MongoDBRepository仓储的实现 (2015-04-08 12:00) MongoDB学习笔 ...

  8. 前端黑客之XSS、CSRF

    XSS:跨站脚本,发生在目标网站中目标用户的浏览器层面上,当用户浏览器渲染整个HTML文档的过程中出现了不被预期的脚本指令并执行时,XSS就会发生. 绝大多数XSS攻击都会采用嵌入一段远程或者第三方域 ...

  9. django的所有app放在一个文件夹下便于管理

    1.新建一个python Package,名字叫apps 2.拖拽以后的app到apps文件夹下,把Search for references勾选去掉,重要重要重要!!!! 3.右键点击apps文件夹 ...

  10. Curl https 访问

    如果访问https的网页,出现: curl: (60) SSL certificate problem: unable to get local issuer certificate 将 将 CURL ...