java spring @Value注解、继承和公共字段,但值不同

3okqufwl  于 2023-11-15  发布在  Java
关注(0)|答案(3)|浏览(190)

我有三个类,其中一个是超类。

class abstract Base {
   public abstract String getV();
}

class A extends Base {
   private String v;
   @Value("${A.v}") public String getV() { return v; };
}

class B extends Base {
   private String v;
   @Value("${B.v}") public String getV() { return v; };
}

字符串
有什么方法可以简化spring @Value annotation的使用吗?我不想复制粘贴所有Base子对象的字段声明和getter。到目前为止,我得到的是:

class abstract Base {
   protected String v;
   public String getV() { return v; };
   public abstract void setV(String v);
}

class A extends Base {
   @Value("${A.v}") public void setV(String v) { this.v = v;};
}

class B extends Base {
   @Value("${B.v}") public void setV(String v) { this.v = v;};
}


有更有效的方法吗?谢谢你的帮助。

0mkxixxg

0mkxixxg1#

我对此表示怀疑。注解不能是动态的。没有办法在抽象的setV方法上放置任何类型的注解来适应子类。你所做的确实是正确的。
不过,我会稍微修改你的代码:

class Base {
   private String v;
   public String getV() { return v; };
   public void setV(String v) { this.v = v; }
}

class A extends Base {
   @Value("${A.v}") public String setV(String v) { super.setV(v); }
}

class B extends Base {
   @Value("${B.v}") public String setV(String v) { super.setV(v); }
}

字符串
我不仅遇到了@Value注解的问题,而且遇到了@Resource/@ Resource注解的问题。
这是我不喜欢自动装配的一个重要原因,我发现自己做了一堆子类,除了用不同的限定符/值自动装配之外没有其他原因。
另一种选择可能是基于java的配置。我知道这与用XML做配置没有太大的区别,但我发现它比XML更干净,当然也比覆盖所有的setter更好。

@Configuration
public class MyConfig {
    @Value("${A.v}")
    private String av;

    @Value("${B.v}")
    private String bv;

    @Bean
    public A a() {
       A a = new A();
       a.setV(av);
    }

    @Bean
    public B b() {
       B b = new B();
       b.setV(bv);
    }
}


然后在XML中:

<context:annotation-config />
<bean class="MyConfig" />

ej83mcc0

ej83mcc02#

另一种方法是:

class abstract Base {
    private String v;
    protected void configure(String v) {
        this.v = v;
    }
}

class A extends Base {
    @Value("${A.v}") private String v;

    @SuppressWarnings("unused")
    @PostConstruct
    private void configure() {
        super.configure(v);
    }
}

class B extends Base {
    @Value("${B.v}") private String v;

    @SuppressWarnings("unused")        
    @PostConstruct
    private void configure() {
        super.configure(v);
    }
}

字符串
这样,如果你有很多值需要在超类中设置,你只需要为每个值设置一个示例变量,并且可以在configure方法中设置它们。

cvxl0en2

cvxl0en23#

我知道这是一个老问题.我最近遇到了类似的挑战,可以在spring Boot 应用程序中使用以下方法解决它。
我有一个带有@Value注解的父类:

package com.example.propertytest;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;

@Getter
@Setter
@ToString
public class PropertyParent {
    @Value("${value}")
    String value;
}

字符串
并且还有子类PropertyChild 1、PropertyChild 2:

package com.example.propertytest;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ConfigurationProperties(prefix = "root.prefix1")
@PropertySource("classpath:application.yaml")
public class PropertyChild1 extends PropertyParent {
}
package com.example.propertytest;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ConfigurationProperties(prefix = "root.prefix2")
@PropertySource("classpath:application.yaml")
public class PropertyChild2 extends PropertyParent {
}

注解@ConfigurationProperties(prefix = "root.prefix1")@ConfigurationProperties(prefix = "root.prefix2")指定application.yaml文件中我的值的前缀:

root:
  prefix1:
    value: a
  prefix2:
    value: b


检查它是否可以工作,例如,通过这样的TestClass:

package com.example.propertytest;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestClass {
    @Autowired
    PropertyChild1 propertyChild1;

    @Autowired
    PropertyChild2 propertyChild2;

    @PostConstruct
    public void info(){
        log.info(propertyChild1.toString());
        log.info(propertyChild2.toString());
    }
}


我有以下结果:

PropertyParent(value=a)
  PropertyParent(value=b)


然而,如果我把配置不是在application.yaml文件中,而是在任何其他文件中,如properties.yaml,并将注解@PropertySource("classpath:application.yaml")更改为@PropertySource("classpath:properties.yaml"),这将不起作用。
我还是想知道为什么...

相关问题