2013-03-15 142 views
4

我想實現的目標是將枚舉注入到Spring管理bean中。如何在spring中使用java枚舉作爲bean

我不希望我的bean配置爲XML(沒有理由除了這個不工作的枚舉)。

我有簡單的Maven項目:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>net.betlista</groupId> 
    <artifactId>test.spring.enum-injection</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-context</artifactId> 
      <version>3.1.3.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aspects</artifactId> 
      <version>3.1.3.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>aspectj</groupId> 
      <artifactId>aspectjrt</artifactId> 
      <version>1.5.4</version> 
     </dependency> 

     <!-- testing --> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>${junit.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>3.1.3.RELEASE</version> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 
    <properties> 
     <junit.version>4.11</junit.version> 
    </properties> 
</project> 

我創建了簡單的測試

import net.betlista.spring.enum_injection.EnumInjectionComponent; 

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 


@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext.xml") 
public class TestClass { 

    @Autowired 
    EnumInjectionComponent component; 

    @Test 
    public void test() { 
     Assert.assertNotNull(component.roundingMode); 
    } 

} 

和我的豆是

package net.betlista.spring.enum_injection; 

import java.math.RoundingMode; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

@Component 
public class EnumInjectionComponent { 

    @Autowired 
    public RoundingMode roundingMode; 

} 

當我試圖運行我的測試IPM越來越

java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enumInjectionComponent': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.math.RoundingMode net.betlista.spring.enum_injection.EnumInjectionComponent.roundingMode; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.math.RoundingMode] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:605) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) 
    at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228) 
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) 
    ... 24 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.math.RoundingMode net.betlista.spring.enum_injection.EnumInjectionComponent.roundingMode; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.math.RoundingMode] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:92) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284) 
    ... 39 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.math.RoundingMode] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:948) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:817) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:731) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:485) 
    ... 41 more 

但在日誌中我可以看到:

信息:在 org.s[email protected]236527f銷燬單身: 定義豆 [org.springframework.context.config.internalBeanConfigurerAspect ,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,enumInjectionComponent,四捨五入,org.springframework.context .annotation.ConfigurationClassPostProcessor.importAwareProcesso R]; 工廠層級的根源

所以我在上下文中四捨五入。

我錯過了什麼?

編輯:我剛發現,問題是隻有Spring版本3.1.x,它的工作原理,任何解決方法可用?

EDIT2:這裏是豆

的定義
<?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.xsd 
    "> 

    <context:spring-configured /> 
    <context:annotation-config /> 
    <context:component-scan base-package="net.betlista"/> 

    <bean id="rounding" class="java.math.RoundingMode" factory-method="valueOf"> 
     <constructor-arg value="UP" /> 
    </bean> 

</beans> 

EDIT3:

的解決方法我用開發中空白的解決方法來指定名單,並在我的豆使用@Value作爲

@Value("#{roundingModes[0]}") 
public RoundingMode roundingMode; 

如果有更好的(更好的)解決方案我希望看到它;-)

+0

您能否澄清一下這個問題?你是否想要注入一個你在某處定義的'RoundingMode'枚舉值?試圖注入枚舉本身沒有任何意義。 – 2013-03-15 18:03:27

+0

這裏不需要'pom.xml'文件,而是粘貼bean xml文件。 – 2013-03-15 18:08:47

+0

已添加上下文配置 @PeterMularien它爲什麼沒有意義?我想要舍入可配置... – Betlista 2013-03-15 18:15:25

回答

1

它應該可以提供裸枚舉名稱並指定值類型。下面是一個舍入模式已被注入列表的例子。對於一個物業也應該是一樣的。

<util:list id="roundingModes" value-type="java.math.RoundingMode"> 
    <value>UP</value> 
</util:list> 
+0

事實上,我不想使用列表,但也許我可以使用EL作爲解決方法... – Betlista 2013-03-19 10:07:10

+1

只要沒有更好的解決方案,現在我接受這個woraround(描述我是如何使用它的有問題 - edit3) – Betlista 2013-03-19 10:52:12

+0

值類型也可以爲bean中的屬性指定。因此,如果有一個名爲'roundingMode'的屬性的bean,應該可以直接使用值類型 – 2013-03-19 12:01:16

1

另一種方法可以是使用最多指定爲字符串,並以bean實現InitializingBean interface並從字符串創建afterPropertiesSet()枚舉。

@Override 
public void afterPropertiesSet() throws Exception { 
    roundingMode = RoundingMode.valueOf(roundingModeName); 
}