没有调用BeanPostProcessor

时间:2011-04-11 16:18:48

标签: java xml spring configuration spring-mvc

这是我的config.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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com">
       <context:include-filter type="assignable" expression="com.coc.frmwk.cmd.Command"/>
       <context:include-filter type="assignable" expression="com.coc.apps.sample.dao.SampleDAO"/>
    </context:component-scan>

<bean id="myPostProcessor" class="com.coc.frmwrk.processors.MyPostProcessor">
</beans>

我知道在使用组件扫描时,将分配给bean的默认范围是“singleton”,除非在xml配置中另外指定或使用注释@Scope,这很酷,但是因为我已经想到了在我的应用程序中,实现特定接口(com.coc.frmwk.cmd.Command)的所有bean都需要将其范围设置为“prototype”,所以我添加了一个实现ScopeMetaDataResolver的类“ScopeResolver”,我做了这个修改我的config.xml,以便容器考虑我的范围解析器:

<context:component-scan base-package="com" scope-resolver="com.coc.frmwk.processors.ScopeResolver">

我的问题是BeanPostProcessor曾经工作得很好,但每当我添加范围解析器时它就会停止被调用(context:component-scan base-package =“com” scope-resolver =“com.xxx。 frmwk.processors.ScopeResolver“),当我省略粗体内容时,它再次起作用。

在配置ScopeResolver时如何使BeanPostProcessor工作? 谢谢,迈赫迪。

修改:这是我的范围解析程序的内容

package com.coc.frmwk.processors;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ScopeMetadata;
import org.springframework.context.annotation.ScopeMetadataResolver;

import com.coc.frmwk.cmd.Command;

public class ScopeResolver implements ScopeMetadataResolver{

    @SuppressWarnings("unchecked")
    @Override
    public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
        ScopeMetadata result = new ScopeMetadata();

        Class c= null;
        try {
            c = Class.forName(definition.getBeanClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (Command.class.isAssignableFrom(c))
        result.setScopeName("prototype");
        else
        result.setScopeName("singleton");

        System.out.println("[Scope Resolver] " + definition.getBeanClassName() + "[" + result.getScopeName() + "]");

        return result;
    }

}

Edit2:我想指出BeanPostProcessor实际上是被调用的,但显然它适用于所有bean,除了那些由ScopeMeteDataResolver改变其范围的bean。

2 个答案:

答案 0 :(得分:3)

您描述的行为是我期望的行为。 (至少在启动时),只要构造bean就调用BeanPostProcessor,只在请求时才构造原型范围的bean。因此,如果您不在任何地方使用此bean,则BeanPostProcessor将不会被调用。

然而,根据您的需要判断您想要修改配方(BeanDefinition而不是创建的bean实例)。要查看食谱,您需要使用BeanFactoryPostProcessor

不同之处在于BeanPostProcessor对bean实例进行操作,其中BeanFactoryPostProcessor适用于bean创建配方(BeanDefinitions)。

答案 1 :(得分:1)

我还没有找到确切的解决问题的方法,但我确实找到了解决方法,这可能对任何有同样问题的人都有用。
而不是使用BeanPostProcessor和MetaDataScopeResolver的组合,我决定使用BeanFactoryPostProcessor来管理范围分辨率和bean处理。 这里是任何感兴趣的人的BeanFactoryPostProcessor的代码:

@Component
public class OaliaBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @SuppressWarnings("unchecked")
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for(String beanName : beanFactory.getBeanDefinitionNames())
        {
            //Scope resolution
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            Class beanClass= null;
            try {
                beanClass = Class.forName(beanDefinition.getBeanClassName());
            } catch (ClassNotFoundException e) {
                // exception handling goes here
            }
            if (Command.class.isAssignableFrom(beanClass))
                beanDefinition.setScope("prototype");

            //Stuff that the BeanPostProcessor do go here
            //..........
            //..........

            System.out.println("[Post Processing] " + beanName + " [" + beanDefinition.getScope() + "]");
        }
        }
    }