2013-03-15 144 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); 
}