2011-04-08 62 views
2

我想知道是否有可能将春天的豆从组件扫描到列表注入列表属性?春天3.0.x - 上下文:组件扫描结果到列表

我使用Spring 3.0.x和Java 6(1.6)。

我迄今为止尝试如下:

<util:list id="converterList"> 
    <context:component-scan base-package="com.company.convert"/> 
</util:list> 
<!-- configure custom b2bde converters --> 
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <list> 
      <ref local="converterList"/> 
     </list> 
    </property> 
</bean> 

,但我得到以下异常:

SEVERE: Exception sending context initialized event to listener instance of class de.hybris.platform.spring.HybrisContextLoaderListener 
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Incorrect usage of element 'context:component-scan' in a nested 
manner. This tag cannot be used nested inside <property>. 
Offending resource: ServletContext resource [/WEB-INF/my-servlet.xml] 

     at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68) 
     at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85) 
     at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.java:284) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseNestedCustomElement(BeanDefinitionParserDelegate.java:1390) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parsePropertySubElement(BeanDefinitionParserDelegate.java:956) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCollectionElements(BeanDefinitionParserDelegate.java:1140) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseListElement(BeanDefinitionParserDelegate.java:1116) 
     at org.springframework.beans.factory.xml.UtilNamespaceHandler$ListBeanDefinitionParser.doParse(UtilNamespaceHandler.java:123) 
     at org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser.parseInternal(AbstractSingleBeanDefinitionParser.java:85) 
     at org.springframework.beans.factory.xml.AbstractBeanDefinitionParser.parse(AbstractBeanDefinitionParser.java:59) 
     at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1335) 
     at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1325) 
     at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135) 
     at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93) 
     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493) 
     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390) 
     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334) 
     at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302) 
     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143) 
     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178) 
     at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149) 
     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124) 
     at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93) 
     at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130) 
     at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467) 
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397) 

难道我缺少一个点或者是不是真的可以扫描豆,放他们到一个列表中,并在财产中使用此列表?

最好的问候, 沃尔特

回答

2

你可能永远不会是能够做到这一点的XML,但使用Java Config(Spring的3功能),它应该是很容易,使用org.springframework.context .annotation.ClassPathScanningCandidateComponentProvider。

更新如下意见

,或者继续使用XML <context:component-scan base-package="com.company.convert"/>获得注册的豆子,然后在Java的配置,使用org.springframework.beans.factory.ListableBeanFactory.getBeansOfType(Class<T>)(从有线式ApplicationContext对象),让他们所有,并调用conversionService的二传手。

+0

嗯,这将意味着,我要重构我们的整个XML配置还是有要能够使用XML配置和Java配置在彼此相结合的方法? – Walter 2011-04-08 09:20:07

+0

我很确定你可以混合使用这两者 - 请参阅第3.11.3.2节“组合Java和XML配置” – artbristol 2011-04-08 09:32:57

+0

我试图用classpathscanningcandidatecomponentprovider实现配置。现在我有了bean定义,并且我错过了正确实例化这些bean的链接并将它添加到列表中。有没有一种方法可以从bean定义中实例化一个bean,而不需要自己实现呢? – Walter 2011-04-08 09:57:20

2

什么defently的工作原理是成才这样的:

Interface Marker{}; 

@Service 
class ServiceA implements Marker {...} 

@Service 
class ServiceB implements Marker {...} 

@Service 
class MyService implements { 

    @Resource 
    private List<Marker> allMarkerImplementations; 

} 

你可以做同样的@Qualifyer代替标记接口。如果你需要一些特殊的豆类,如您需要,我会找一个其他的解决办法

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Qualifier 
public @interface InterestingService {} 

@InterestingService 
@Service 
class ServiceA {...} 

@InterestingService 
@Service 
class ServiceB {...} 

@Service 
class MyService implements { 

    @Resource 
    @InterestingService 
    private List<Object> allInterestingServices; 

} 

这己技巧是有帮助的。

+0

我了解标记接口方法。我能够使用收集xml中标记接口的所有实现的属性将它设置为转换器列表吗? – Walter 2011-04-08 09:18:46

+0

这是一个(不是100%)xml免费解决方案。我想:如果你使用组件scann,比你使用所有其他“现代”的Spring东西,并不需要XML。 – Ralph 2011-04-08 09:26:08

2

定稿我实现了以下方法:

的Spring XML配置:

<!-- java config provides the conversionService factory bean --> 
<bean name="myCompanyJavaConfig" class="com.company.config.MyCompanySpringConfig"/> 

<!-- scans all converters which will be picked up by the MyCompanySpringConfig and will be registers as list to conversion service--> 
<context:component-scan base-package="com.company.convert"/> 


<!-- activates annotation driven binding --> 
<!-- the conversion service is registered by the java config MyCompanySpringConfig --> 
<mvc:annotation-driven conversion-service="conversionService" validator="validator"/> 

实现的Java配置的:

package com.company.config; 

import java.util.LinkedHashSet; 
import java.util.Map; 
import java.util.Set; 

import org.springframework.beans.factory.FactoryBean; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.support.ConversionServiceFactoryBean; 
import org.springframework.core.convert.ConversionService; 
import org.springframework.core.convert.converter.Converter; 

@Configuration 
public class MyCompanySpringConfig 
{ 

    @Autowired 
    private ApplicationContext applicationContext; 

    public @Bean 
    FactoryBean<ConversionService> conversionService() 
    { 
     ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean(); 
     conversionServiceFactoryBean.setConverters(converters()); 
     return conversionServiceFactoryBean; 
    } 

    public @Bean 
    Set<Converter> converters() 
    { 
     Map<String, Converter> converterBeans = applicationContext.getBeansOfType(Converter.class); 
     return new LinkedHashSet<Converter>(converterBeans.values()); 
    } 
} 

,如果它是一个完美的方式?我不知道;-)但我知道的是,它现在起作用。

感谢所有回复。

最好的问候, 沃尔特