Spring Container的扩展点

转自: 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方法,不用在代码里主动的去调用.

时间: 2025-01-08 14:27:13

Spring Container的扩展点的相关文章

Spring容器相关扩展点

// 如果容器内的bean实现了该接口,那么在容器中实例化任何其他bean之前都会回调该方法来对bean的配置元数据进行修改 public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; } // 通知接口 public interface Aware { } // 常用: //

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

Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,易于扩展,性能也很优秀.他和Struts2的思想还是一样的都有一个前端拦截器进行请求转发,只不过Struts2是filter,spring mvc是servlet,但spring mvc非常简单不论是学习还是使用. 这是spring3 mvc的核心流程图: SpirngMVC的第一个扩展点  HandlerMapping接口 -- 处理请求的映射 保存请求url到具体的方法的映射关系,,我们可以编写任意的HandlerMa

spring之扩展点

               spring之扩展点 上篇文章,介绍了spring中bean的生命周期,并且在文章末尾提到,spring使用BeanPostProcessor接口来处理生命周期的回调.我们可以在初始化函数(init())中定制化一些逻辑.上述BeanPostProcessor就是spring扩展点(extension points).Spring及其灵活,一般情况下我们并不需要去继承ApplicationContext 去扩展功能,只需要使用spring提供的扩展接口,就可以刻sp

Spring开闭原则的表现-BeanPostProcessor扩展点-2

上接Spring提供的BeanPostProcessor的扩展点-1继续分析. 四.BeanPostProcessor接口及回调方法图  从图中我们可以看出一共五个接口,共十个回调方法,即十个扩展点,但我们之前的文章只分析了其中八个,另外两个稍候也会解析一下是干什么的. =================================================================== ==============================================

Spring源码系列 — BeanDefinition扩展点

前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition,再到容器扩展点,最后到Bean创键,这个过程中无处不存在Spring预留的扩展口. 本篇文章介绍Spring的另一种扩展点:BeanDefinition扩展点,该扩展点是为处理BeanDefinition而设计.本文主要从以下几点分析: BeanDefinition扩展点的几种方式 BeanDef

玩转Asp.net MVC 的八个扩展点

MVC模型以低耦合.可重用.可维护性高等众多优点已逐渐代替了WebForm模型.能够灵活使用MVC提供的扩展点可以达到事半功倍的效果,另一方面Asp.net MVC优秀的设计和高质量的代码也值得我们去阅读和学习. 本文将介绍Asp.net MVC中常用的八个扩展点并举例说明. 一.ActionResult ActionResult代表了每个Action的返回结果.asp.net mvc提供了众多内置的ActionResult类型,如:ContentResult,ViewResult,JsonRe

17+个ASP.NET MVC扩展点,含源码{转}

1.自定义一个HttpModule,并将其中的方法添加到HttpApplication相应的事件中!即:创建一个实现了IHttpmodule接口的类,并将配置WebConfig.在自定义的HttpModule中,可以将一个方法注册到HttpApplication的任意一个事件中,在之后执行HttpApplication一些列事件时,按照事件的顺序(事件又按照添加方法先后的顺序)执行注册在事件中的方法! namespace MvcStore.Models { public class Excute

Eclipse平台SDK支持的扩展点

org.eclipse.ant.core.antTasks:将Ant的任务与你的插件中的类关联起来,以扩展Ant在Eclipse中运行时的能力.org.eclipse.ant.core.antTypes: 将Ant的数据类型与你插件中的类关联起来.org.eclipse.ant.core.extraClasspathEntries :提供额外的类型库(JAR 文件)给Ant使用.org.eclipse.compare.contentMergeViewers:为一种或多种文件类型提供一个比较/合并

eclipse插件开发菜单(Menu)功能及其扩展点

Eclipse 具有丰富的菜单功能,给开发人员提供了很好的用户体验.总体而言,Eclipse 菜单种类包括视图 / 编辑器菜单,主菜单(Main Menu),视图 / 编辑器菜单(ViewPart/EditorPart Menu)和上下文菜单(Context Menu).插件开发人员通过灵活应用这些菜单,可以给用户提供很好的体验.由于视图和编辑器菜单功能类似,因此本文重点讲述视图菜单(视图下拉菜单及其工具栏菜单),除此之外,还将讲述主菜单和上下文菜单. 如图 1 所示为 Project Expl