【问题标题】:spring beanpostprocessor doesn't work on component-scan?spring beanpostprocessor 不适用于组件扫描?
【发布时间】:2009-07-13 19:30:27
【问题描述】:

我有很多千篇一律的spring bean,不想在xml 中明确定义每一个。所以我去了组件扫描路线,这让我可以做到这一点。这很好,但我刚刚意识到没有为使用组件扫描技术加载的 bean 调用 MyBeanPostProcessor。 MyBeanPostProcessor 只是尝试对这些 bean 进行一些 setter 注入。下面的配置只是显示了我尝试过的这种方法,它不起作用。还有其他想法如何在这些 bean 上进行 setter 注入吗?

我正在使用 Spring 2.5.5

谢谢, 本

<context:component-scan base-package="us.benanderson" 
        use-default-filters="false" 
        annotation-config="false"
        scope-resolver="us.benanderson.MyScopeResolver"
        name-generator="us.benanderson.MyBeanNameGenerator">
    <context:include-filter type="custom" expression="us.benanderson.MyTypeFilter" />
</context:component-scan>
<bean class="us.benanderson.MyBeanPostProcessor">
    <property name="order" value="500" />
</bean>

【问题讨论】:

  • 如果您尝试显式添加 bean 定义而不是使用类路径扫描会发生什么?你能确认后处理器在这种情况下工作吗?
  • 是的,我确实确认 beanpostprocessor 在这种情况下工作
  • 您是否正在寻找 BeanPostProcessor 的替代品进行注射?或者您的主要目标是让组件扫描在使用或不使用 BeanPostProcessor 的情况下工作吗?
  • 替代品会很好,尽管我不确定是否有任何替代品。我的要求是: - 无需显式定义它们的自动加载 bean - 执行一些简单的 setter 注入“没有为使用组件扫描技术加载的 bean 调用 MyBeanPostProcessor。”我真的不知道还能怎么说这个。使用组件扫描技术定义的 bean 不会被传递给 MyBeanPostProcessor。 MyBeanPostProcessor 只是试图进行一些 setter 注入。 MyBeanPostProcessor 适用于我在 xml 中明确定义的 bean。
  • 我创建了一个小测试用例,它非常适合我。即使我关闭了注释配置并使用了自定义类型过滤器。我认为您最好的选择是尝试退后几步:尝试隔离问题。我看到你有自己的作用域解析器——这可能是罪魁祸首(不是说它应该引起问题——尽管它是一种可能性)。

标签: java spring


【解决方案1】:

这是我的测试用例,它似乎有效(Spring 2.5.6)。为了简洁起见,我考虑过排除一些文件,但我决定不这样做。

Start.java(入口点)

package se.waxwing.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Start {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("se/waxwing/test/Context.xml");
        context.getBean("customBean");
    }
}

上下文.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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">


    <context:component-scan base-package="se.waxwing.test" 
        use-default-filters="false" 
        annotation-config="false"
        scope-resolver="se.waxwing.test.MyScopeResolver">
        <context:include-filter type="custom" expression="se.waxwing.test.MyTypeFilter" />
    </context:component-scan>

    <bean id="beanProcessor" class="se.waxwing.test.MyBeanPostProcessor" />

</beans>

CustomBean.java(这是我要查找的 - 请参阅 MyTypeFilter)

package se.waxwing.test;

public class CustomBean {

    public CustomBean() {
        System.err.println("instantiating component");
    }
}

MyBeanPostProcessor.java

package se.waxwing.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.err.println("after " + beanName);
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.err.println("before " + beanName);
        return bean;
    }   
}

MyScopeResolver.java

package se.waxwing.test;

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

public class MyScopeResolver implements ScopeMetadataResolver {

    @Override
    public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
        ScopeMetadata result = new ScopeMetadata();
        result.setScopedProxyMode(ScopedProxyMode.NO);
        result.setScopeName("prototype");
        return result;
    }

}

MyTypeFilter.java

package se.waxwing.test;

import java.io.IOException;

import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

public class MyTypeFilter implements TypeFilter {

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        return metadataReader.getClassMetadata().getClassName().equals(CustomBean.class.getCanonicalName());
    }
}

这会产生以下输出:

2009-aug-26 15:44:02 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO:刷新org.springframework.context.support.ClassPathXmlApplicationContext@c1b531:显示名称[org.springframework.context.support.ClassPathXmlApplicationContext@c1b531];启动日期 [2009 年 8 月 26 日星期三 15:44:02 CEST];上下文层次的根 2009-aug-26 15:44:02 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息:从类路径资源 [se/waxwing/test/Context.xml] 加载 XML bean 定义 2009 年 8 月 26 日 15:44:02 org.springframework.context.support.AbstractApplicationContext 获得FreshBeanFactory 信息:应用程序上下文的 Bean 工厂 [org.springframework.context.support.ClassPathXmlApplicationContext@c1b531]:org.springframework.beans.factory.support.DefaultListableBeanFactory@121f1d 2009-aug-26 15:44:02 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息:在 org.springframework.beans.factory.support.DefaultListableBeanFactory@121f1d 中预实例化单例:定义 bean [customBean,beanProcessor];工厂层次结构的根 实例化组件 在 customBean 之前 在 customBean 之后

所以,如您所见,customBean bean 被我的类型过滤器发现,作为 bean 添加,当applicationContext.getBean("customBean") 被调用时,一个新对象被实例化,然后它被传递给我的后 bean 处理器。

【讨论】:

  • 我是个白痴!在我下载了 spring 2.5.6 并试用后(它仍然坏了),我注意到我没有调用 applicationContext.getBean("customBean") 的事实!所以它实际上一直在为我工作——只是我确认它坏了的方式!感谢您提交代码并确认其有效。我想给你赏金,但我不知道怎么做。没有复选框或任何东西 - 根据这个:meta.stackexchange.com/questions/13421/…我猜你不走运?
  • 没问题,它让我可以使用自定义范围解析器和类型过滤器,这是一件好事。猜猜我在那个赏金上不走运 - 无法对抗系统。 :)
【解决方案2】:

在应用程序上下文加载后,检查您已注释的 bean 是否可用。

我怀疑你已经关闭了“annotation-config”,它忽略了你的注释。

【讨论】:

  • 是的,我已验证 bean 可用。我写了自己的过滤器,这就是我关闭注释配置的原因。
猜你喜欢
  • 1970-01-01
  • 2018-07-18
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 2012-08-08
相关资源
最近更新 更多