用于自定义类的Spring @Value属性

时间:2014-09-26 15:32:38

标签: spring

是否可以使用Spring的@Value批注来读写自定义类类型的属性值?

例如:

@Component
@PropertySource("classpath:/data.properties")
public class CustomerService {

    @Value("${data.isWaiting:#{false}}")
    private Boolean isWaiting;

    // is this possible for a custom class like Customer???
    // Something behind the scenes that converts Custom object to/from property file's string value via an ObjectFactory or something like that?
    @Value("${data.customer:#{null}}")
    private Customer customer;

    ...
}

已编辑解决方案

以下是我使用Spring 4.x API ...

的方法

为Customer类创建了新的PropertyEditorSupport类:

public class CustomerPropertiesEditor extends PropertyEditorSupport {

    // simple mapping class to convert Customer to String and vice-versa.
    private CustomerMap map;

    @Override
    public String getAsText() 
    {
        Customer customer = (Customer) this.getValue();
        return map.transform(customer);
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException 
    {
        Customer customer = map.transform(text);
        super.setValue(customer);
    }
}

然后在应用程序的ApplicationConfig类中:

@Bean
public CustomEditorConfigurer customEditorConfigurer() {

    Map<Class<?>, Class<? extends PropertyEditor>> customEditors = 
            new HashMap<Class<?>, Class<? extends PropertyEditor>>(1);
    customEditors.put(Customer.class, CustomerPropertiesEditor.class);

    CustomEditorConfigurer configurer = new CustomEditorConfigurer();
    configurer.setCustomEditors(customEditors);

    return configurer;
}

干杯, PM

4 个答案:

答案 0 :(得分:7)

您必须创建一个扩展PropertyEditorSupport

的类
public class CustomerEditor extends PropertyEditorSupport {
  @Override
  public void setAsText(String text) {
    Customer c = new Customer();
    // Parse text and set customer fields...
    setValue(c);
  }
}

答案 1 :(得分:1)

可以阅读Spring文档。你可以看到这个例子: 用法示例

 @Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {
     @Autowired
     Environment env;

     @Bean
     public TestBean testBean() {
         TestBean testBean = new TestBean();
         testBean.setName(env.getProperty("testbean.name"));
         return testBean;
     }
 }

查看详情here

答案 2 :(得分:0)

Spring可以读取属性并将其直接加载到类中。
此外,您可以在类的顶部添加@ConfigurationProperties(prefix = "data"),而不是通过使代码更简洁来逐个连接每个嵌套属性。

给出所有说明,这是带有说明的最终示例:

// File: CustomerConfig.java
@Configuration
// Set property source file path (optional)
@PropertySource("classpath:/data.properties")
// Put prefix = "data" here so that Spring read properties under "data.*"
@ConfigurationProperties(prefix = "data") 
public class CustomerConfig {
    // Note: Property name here is the same as in the file (data.customer)
    // Spring will automatically read and put "data.customer.*" properties into this object
    private Customer customer; 

    // Other configs can be added here too... without wiring one-by-one

    public setCustomer(Customer customer){
        this.customer = customer;
    }

    public getCustomer(){
        return this.customer;
    }
}

就是这样,现在您具有“ data.customer。*”属性,可以通过CustomerConfig.getCustomer()进行加载和访问。


要将其集成到您的服务中(基于示例代码):

// File: CustomerService.java
@Component
@PropertySource("classpath:/data.properties")
public class CustomerService {

    @Value("${data.isWaiting:#{false}}")
    private Boolean isWaiting;

    @Autowired // Inject configs, either with @Autowired or using constructor injection
    private CustomerConfig customerConfig;

    public void myMethod() {
        // Now its available for use
        System.out.println(customerConfig.getCustomer().toString());
    }
}

通过这种方式,无需“魔术技巧”即可将配置读入类。 请查看@ConfigurationProperties文档/示例,以及此post以获得更多有用的信息。


注意:由于
,我建议使用PropertyEditorSupport 反对 a)它是为不同目的而构建的,将来可能会因破坏代码而改变
b)它需要在内部手动进行“处理”代码=>可能的错误
取而代之的是使用为此目的而专门构建的东西(Spring已经拥有了),以便使代码更易于理解,并获得可能在将来(或现在)进行的内部改进/优化。 >

进一步的改进:您的CustomerService似乎也被配置(@PropertyService)弄得乱七八糟。我建议也通过另一个类读取这些属性(类似),然后在此处连接该类,而不是在CustomerService中完成所有操作。

答案 3 :(得分:0)

如果你想将它与列表一起使用,有一个使用数组的解决方法。

将您的财产定义为 Customer[] 而不是 List 然后:

在 ApplicationConfig 类中:

@Bean
public CustomEditorConfigurer customEditorConfigurer() {

    Map<Class<?>, Class<? extends PropertyEditor>> customEditors = 
            new HashMap<Class<?>, Class<? extends PropertyEditor>>(1);
    customEditors.put(Customer.class, CustomerPropertiesEditor.class);
    customEditors.put(Customer[].class, CustomerPropertiesEditor.class);

    CustomEditorConfigurer configurer = new CustomEditorConfigurer();
    configurer.setCustomEditors(customEditors);

    return configurer;
}

在客户编辑器中:

public class CustomerEditor extends PropertyEditorSupport {
  public static final String DEFAULT_SEPARATOR = ",";

  @Override
  public void setAsText(String text) {
    String[] array = StringUtils.delimitedListToStringArray(text, this.separator);
    if (this.emptyArrayAsNull && array.length == 0) {
        super.setValue((Object) null);
    } else {
        if (this.trimValues) {
            array = StringUtils.trimArrayElements(array);
        }
        
        // Convert String[] to Customer[]   
        super.setValue(...);
    }
  }
}