【问题标题】:Use application.properties in a non-spring injected class在非弹簧注入类中使用 application.properties
【发布时间】:2020-03-30 12:05:49
【问题描述】:

我在此类 B 中有一个使用 new B(this); 创建的类,我想使用 application.properties 中的值。但是因为(据我所知)因为它不是用 Spring 创建的,所以它不会有任何注入(我使用 @Value 注释)

这就是类的创建方式:

@Component
public class A {

    public B getB(){return new B(this);}

    /**
        a lot more stuff
    **/
}

有问题的班级:

public class B {

    private A a;

    public B(A a){
        this.a = a;
    }

    @Value("${threshold}")
    private String threshold;  //this is null because it's not created with Spring

    public String getThreshold(){
        return threshold;
    }
    /**
        a lot more stuff
    **/

}

所以我的问题如下:

1) 如何使用 application.properties 文件中的值或

2) 我如何写 B 是用 Spring 创建的?

一些背景资料:

  • 我没有写初始代码所以我不想改变太多 但想对其进行修改,以便将来可以更好地维护
  • 我没有那么多 Spring 知识,只是开始了解更多 并且更加熟悉它。
  • 在第 2 点)由于构造函数以及如何通过 Spring 设置它,我正在苦苦挣扎...

任何帮助将不胜感激

【问题讨论】:

  • 您可以首先将配置属性隔离到单独的 POJO 中。然后让 spring boot 将值注入 POJO。您可以使用 @Autowire 来创建该配置 POJO 的实例,无论您希望在哪里使用这些值。如果您需要,我会发布一个示例。
  • 不胜感激,我想我知道你的意思,但不完全确定。
  • 好的。我会为你发布一个示例答案。
  • 既然A 是一个bean,你为什么不从中获得价值呢? public B(A a){ this.a = a; this.threshold = a.getThreshold(); }
  • 刚刚在getB()方法上注释了@Bean

标签: java spring-boot javabeans properties-file


【解决方案1】:

这是一个使用@ConfigurationPropertiesapplication.properties 绑定到 POJO 的示例。

假设你有一个像这样的application.properties 文件,

mail.hostname=mailer@mail.com
mail.port=9000

您可以为上述场景创建这样的 POJO。

注意:如果您的 Spring Boot 版本低于 2.2,您可能还需要使用 @Configuration@Component 注释此类)

@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {

    private String hostname;
    private String port;

    // Create Getters and Setters

}

spring boot 应用程序初始化时,会自动将application.properties中的值映射到这个POJO中。如果你想使用它,你所要做的就是创建一个变量并用@Autowire标记它

@Component
public class TestClass {

    @Autowire
    private ConfigProperties properties;

    public void printSomething() {
       System.println(properties.getHostname());
       System.println(properties.getPort());
    }

}

正在跟进您的问题...

由于您示例中的类不是由 spring 管理的,并且由于某种原因您必须保持这种方式,因此您可以使用以下帮助程序类在非 spring 管理的类中手动自动装配 spring bean。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

@Service
public class BeanUtil implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    /**
     *Use this method to manually autowire Spring Beans into classes that are not managed by Spring.
     *
     *@param beanClass - Class type of the required bean.
     **/
    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

}

要在您的 class B 中使用它,请执行以下操作。

public class B {

    private ConfigProperties properties;

    public B() {
        BeanUtil.getBean(ConfigProperties.class); // This will initialize properties variable properly.
    }

    public void printSomething() {
       System.println(properties.getHostname());
       System.println(properties.getPort());
    }

}

【讨论】:

  • 这似乎不是问题的解决方案。最初的问题是如何在 POJO 中使用属性,但是您不能将 bean 注入或自动装配到 POJO 中。这就像@Boendal 在A 类中写@Value("${threshold}") private String threshold; 一样
  • @YuriyTsarkov 这不是关于他在问什么,而是关于他需要什么。无论如何,他问“我怎样才能使用 application.properties 中的值”。这就是我发布此答案的原因。
【解决方案2】:

你可以这样写:

@Component
public class A {

    @Value("${threshold}")
    private String threshold;

    public B getB(){
        return new B(this);
    }

    public String getThreshold() {
        return threshold;
    }

}

public class B {

    private A a;
    private String threshold;

    public B(A a){
        this.a = a;
        this.threshold=a.getThreshold();
    }

    public String getThreshold(){
        return threshold;
    }

}

【讨论】:

    【解决方案3】:

    您可以创建一个类,该类将直接从文件中为您加载属性。 该文件必须在资源包中。

    定义这些属性的配置属性类

    @ConfigurationProperties(prefix = "reader")
    public class ReaderProperties {
        private String threshold;
    }
    

    属性类

    import java.util.Properties;
    
    class MyProperties {
    
        private final Properties props;
    
        private MyProperties(Class<?> propertiesClass) throws IOException {
            this.props = new Properties();
            this.props.load(propertiesClass.getResourceAsStream("/application.properties"));
        }
        
        public String getThreshold() {
            return props.getProperty("threshold");
        }
    
    }
    

    然后在B里面:

    public class B {
    
        private A a;
        private String threshold;
    
        public B(A a){
            this.a = a;
            MyProperties props = new MyProperties(ReaderProperties.class);
            this.threshold = props.getThreshold();
        }
    
        public String getThreshold(){
            return threshold;
        }
        /**
            a lot more stuff
        **/
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      相关资源
      最近更新 更多