Spring限定符和属性占位符

时间:2011-10-18 19:45:31

标签: java spring dependency-injection

是否有人知道我是否应该将属性占位符用作限定符中的表达式?我似乎无法让这个工作。

我正在使用spring 3.0.4。

@Controller
public class MyController {
   @Autowired
   @Qualifier("${service.class}")
   Service service;
}

@Service
@Qualifier("ServiceA")
ServiceA implements Service {
   public void print() {
       System.out.println("printing ServiceA.print()");
   } 
}

@Service
@Qualifier("ServiceB")
ServiceB implements Service {
   public void print() {
      System.out.println("printing ServiceB.print()");
   } 
}

XML:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/etc/config.properties"/>
</bean>

config.properties:

config.properties
service.class=serviceB

5 个答案:

答案 0 :(得分:40)

这很有效。如果只使用默认的spring bean名称,则可以不使用服务名称。 serviceA vs ServiceA等

@Controller
class MyController {
@Autowired(required=false)
@Qualifier("Service")
Service service;

public static void main(String[] args) {
   ApplicationContext context = new ClassPathXmlApplicationContext("app-ctx.xml", MyController.class);
   for(String s:context.getBeanDefinitionNames()){
       System.out.println(s);
       for(String t:context.getAliases(s)){
           System.out.println("\t" + t);
       }
   }
   context.getBean(MyController.class).service.print();
  }
}

public interface Service {
    void print();
}

@Service(value="ServiceA")
public class ServiceA implements example.Service {
    public void print() {
        System.out.println("printing ServiceA.print()");
    } 
}

@Service(value="ServiceB")
public class ServiceB implements example.Service {
    public void print() {
        System.out.println("printing ServiceB.print()");
    } 
}

XML:

<beans>
    <alias name="${service.class}" alias="Service"/>
    <context:property-placeholder location="example/app.properties"/>
    <context:component-scan base-package="example"/>
<beans>

道具:

service.class=ServiceB

答案 1 :(得分:7)

此解决方案不使用XML和属性文件。

你的课程改进了:

MyController.java

@Controller
public class MyController {
    @Autowired
    public MyController(@Qualifier("MyServiceAlias") MyService myService) {
        myService.print();
    }
}

ServiceA.java

@Service("serviceA")
public class ServiceA implements MyService {
    @Override
    public void print() {
        System.out.println("printing ServiceA.print()");
    }
}

ServiceB.java

@Service("serviceB")
public class ServiceB implements MyService {
    @Override
    public void print() {
        System.out.println("printing ServiceB.print()");
    }
}

application.properties(这里你可以改变要加载的类):

service.class=serviceA

重要的配置文件AppConfig.java

@Configuration
public class AppConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public MyService MyServiceAlias(@Value("${service.class}") String qualifier) {
        return (MyService) context.getBean(qualifier);
    }
}

补充说明:

  • 仅对将要自动装配的字段使用@Qualifier。对于服务,要指定bean名称,请使用@Service
  • 如果您需要标准bean名称,则不需要使用带有specyify名称的@Service。例如,ServiceA的标准bean名称为serviceA(不是ServiceA - 请参阅大字母第一个字母),因此@Service("serviceA")冗余(@Service就够了)。
  • 我基于AppConfig对此答案Spring Bean Alias in JavaConfig
  • 此解决方案优于此Spring Qualifier and property placeholder,因为您不需要XML。
  • 在Spring Boot 1.5.7上测试。

答案 2 :(得分:4)

我冒昧地猜测答案是否定的,只是基于几个javadoc页面中的写作。例如,请参阅@Value的文档:

http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html

请注意,他们特别提到在注释中使用表达式。相比之下,@Qualifier的文档:

http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Qualifier.html

没有提及表达方式。显然不是一个明确的答案(但春天在文档上通常非常好)。此外,如果@Qualifier注释支持表达式,我希望它们的工作方式与@Value注释相同(仅基于spring是一个非常一致的框架)。

Spring 3.1具有新的配置文件bean功能,看起来它可以完成类似于你想要做的事情。这是为此写的:

http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/

答案 3 :(得分:1)

作为一个工作环境,您可以在config.properties中根据其名称设置所需的Spring服务实现。

@Controller
public class MyController {
  //add a String which will hold the name of the service to implement
  @Value("${service.class}")
  private String serviceToImplement;

  Service service;

  // now autowire spring service bean based on int name using setter
  @Autowired
  public void setService(ApplicationContext context) {
    service = (Service) context.getBean(serviceToImplement);
   }
}

@Service
 @Qualifier("ServiceA")
 ServiceA implements Service {
  public void print() {
   System.out.println("printing ServiceA.print()");
  } 
}

 @Service
 @Qualifier("ServiceB")
 ServiceB implements Service {
   public void print() {
    System.out.println("printing ServiceB.print()");
   } 
}

config.properties

service.class=serviceB

答案 4 :(得分:-5)

也许给这个旋转:

@Controller
public class MyController {

   private String serviceId;

   @Value("${serviceId}")
   public void setServiceId(String serviceId) {
      this.serviceId = serviceId;
   }

   @Autowired
   @Qualifier(serviceId)
   Service service;
}