繁体   English   中英

在非弹簧注入类中使用 application.properties

[英]Use application.properties in a non-spring injected class

我有一个用new B(this); 在此类 BI 中,想要使用 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 设置它......

任何帮助,将不胜感激

这是一个使用@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());
    }

}

你可以写如下:

@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;
    }

}

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

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

@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
    **/

}

如果您愿意并且能够使用@ConfigurationProperties注释B类,则现有答案有效,但如果B作为非 Spring 库的一部分提供,或者如果B需要在非 Spring 项目中使用,这可能不可行。

幸运的是,如果B是 POJO/JavaBean,Spring 确实提供了一种更可移植的方法:

示例B类:

public class B {
    private String threshold;
    // Is a POJO/JavaBean i.e. has default constructor, getters, setters etc.
}

application.properties

my.config.prefix.threshold=42

@Configuration类中为您的 Spring Boot 项目定义一个 Spring bean,例如:

@Configuration
public class ApplicationConfig {
    @Bean
    @ConfigurationProperties("my.config.prefix")
    public B getB() {
        // Spring will later use setters to configure the fields per my.config.prefix
        return new B();
    }
}

您现在可以依靠 Spring 来自动装配依赖关系,例如使用字段注入1

@Component
public class A {
    @Autowired
    private B b; // b.getThreshold() == 42
}

除非一个类严格用于运行或配置 Spring Boot 应用程序,否则我会错误地通过定义 bean 来保持代码更具可移植性。


1一般不推荐现场注入,但为了简洁,这里使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM