Spring autowire using annotations and a type defined in a properties file?

My goal is a framework where concrete types of beans can be easily changed by a properties file. I also prefer annotations to XML. Ideally I'd to use a combination of @Resource and SpEL like this:

@Resource(type="#{myProperties['enabled.subtype']}")
SomeInterface foo;

where I've loaded myProperties with a PropertiesFactoryBean or <util:properties> from a file that includes:

enabled.type = com.mycompany.SomeClassA; // which implements SomeInterface

This doesn't work because the argument of type must be a literal, ie, no SpEL allowed. What's the best practice here?

Update: See my answer below.


This is exactly the use case for Spring Java Configuration.

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java

Or you can alternatively make a Factory.

Using: org.springframework.beans.factory.FactoryBean<SomeInterface>

The name of the bean that implements FactoryBean will be seen as a "SomeInterface" even though its not.


I think it is not possible, the solution I tend to adopt is to use a factory that creates the different objects depending on a configuration property (enabled.type in your example).

A second alternative could be to use injection by name:

@Resource(name="beanName")

And last, if you use Spring 3.1+ you can try to use profiles, and have different bean sets in different profiles, if that solves your problem.


Spring's Java Configuration and Bean Definition Profiles turn out to be exactly what I was looking for (thanks @Adam-Gent and @Guido-Garcia). The former seems necessary for the dynamic element, and the latter promotes a better practice.

Here's a solution with Java config and properties:

@Configuration
public class SomeClassConfig {
    @Value("#{myProperties['enabled.subtype']}")
    public Class enabledClass;

    @Bean SomeInterface someBean() 
              throws InstantiationException, IllegalAccessException {
       return (SomeInterface) enabledClass.newInstance();
    }   
}

Here's a slightly less dynamic solution with profiles.

@Configuration
@Profile("dev")
public class DevelopmentConfig {
    @Bean SomeInterface someBean() {
       return new DevSubtype();
    }   
}

@Configuration
@Profile("prod")
public class ProductionConfig {
    @Bean SomeInterface someBean() {
       return new ProdSubtype();
    }   
}

With profiles, the active profile(s) are declared using one of a variety of methods such as via system property, JVM property, web.xml, etc. For example, with a JVM property:

-Dspring.profiles.active="dev"
链接地址: http://www.djcxy.com/p/10770.html

上一篇: 获取不在括号内的维基百科文章中的第一个链接

下一篇: Spring自动装配使用注释和属性文件中定义的类型?