java Spring 自动装配自动装配 bean 中的属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30080337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 16:25:14  来源:igfitidea点击:

Spring Autowiring a property within an autowired bean

javaspringspring-boot

提问by anset

I'm a newbie to Spring. I'm facing a problem with Spring-Boot. I'm trying to autowire a field from an external config file into an autowired bean. I have the following classes

我是 Spring 的新手。我正面临 Spring-Boot 的问题。我正在尝试将外部配置文件中的字段自动装配到自动装配的 bean 中。我有以下课程

App.java

应用程序.java

public class App {

@Autowired
private Service service;

public static void main(String[] args) {

    final SpringApplication app = new SpringApplication(App.class);
    //app.setShowBanner(false);
    app.run();
}

@PostConstruct
public void foo() {
    System.out.println("Instantiated service name = " + service.serviceName);
}
}

AppConfig.java

应用程序配置文件

@Configuration
@ConfigurationProperties
public class AppConfig {

@Bean
public Service service()    {
    return new Service1();
}
}

Service Interface

服务接口

public interface Service {
    public String serviceName ="";
    public void getHistory(int days , Location location );
    public void getForecast(int days , Location location );
}

Service1

服务1

@Configurable
@ConfigurationProperties
public class Service1 implements Service {

@Autowired
@Value("${serviceName}") 
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.



public void getHistory(int days , Location location)
{
    //history code
}

public void getForecast(int days , Location location )
{
    //forecast code
}
}

I'm unable to display the service name variable in the postconstruct method of the App class. Am I doing this right?

我无法在 App 类的 postconstruct 方法中显示服务名称变量。我这样做对吗?

采纳答案by Eddú Meléndez

You can load properties in different ways:

您可以通过不同方式加载属性:

Imagine the following application.properties which is automatically loaded by spring-boot.

想象以下由 spring-boot 自动加载的 application.properties。

spring.app.serviceName=Boot demo
spring.app.version=1.0.0
  1. Inject values using @Value

    @Service
    public class ServiceImpl implements Service {
    
    @Value("${spring.app.serviceName}") 
    public String serviceName;
    
    }
    
  2. Inject values using @ConfigurationProperties

    @ConfigurationProperties(prefix="spring.app")
    public class ApplicationProperties {
    
       private String serviceName;
    
       private String version;
    
       //setters and getters
    }
    
  1. 使用@Value 注入值

    @Service
    public class ServiceImpl implements Service {
    
    @Value("${spring.app.serviceName}") 
    public String serviceName;
    
    }
    
  2. 使用@ConfigurationProperties 注入值

    @ConfigurationProperties(prefix="spring.app")
    public class ApplicationProperties {
    
       private String serviceName;
    
       private String version;
    
       //setters and getters
    }
    

You can access to this properties from another class using @Autowired

您可以使用从另一个类访问此属性 @Autowired

@Service
public class ServiceImpl implements Service {

@Autowired
public ApplicationProperties applicationProperties;

}

As you can notice the prefix will be spring.appthen spring-boot will match the properties prefix with that and look for serviceNameand versionand values will be injected.

如您所见,前缀将是,spring.app然后 spring-boot 将匹配属性前缀,并查找serviceNameandversion和值将被注入。

回答by Joao Evangelista

Considering you have you class Appannotated with @SpringBootApplicationand Appclass in the top package You can put your serviceNameinside application.propertiesand inject it using @Value("${serviceName}"). Do not use @Componenton a class if you are already using @Beanon configuration it will clash, and so @Autowiredwith @Value

考虑到您在顶级包中App使用@SpringBootApplication和class注释了您的类,App您可以将其放入serviceName内部application.properties并使用@Value("${serviceName}"). @Component如果您已经@Bean在配置上使用,请不要在类上使用它会发生冲突,因此@Autowired@Value

See docsfor more info

查看文档了解更多信息

You will end with something like

你会以类似的东西结束

@Service // @Component specialization
public class Service1 implements Service {

@Value("${serviceName}") 
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.



public void getHistory(int days , Location location)
{
    //history code
}

public void getForecast(int days , Location location )
{
    //forecast code
}
}

No need for @Bean declaration when you have @Component/@Service/@Repository

当你有@Component/@Service/@Repository 时不需要@Bean 声明

@Configuration
public class AppConfig {  //other stuff here not duplicated beans  }

And your main class

还有你的主课

    package com.app;

    @SpringBootApplication // contains @EnableAutoConfiguration @ComponentScan @Configuration   
    public class App {

    @Autowired
    private Service service;

    public static void main(String[] args) {

        final SpringApplication app = new SpringApplication(App.class);
        //app.setShowBanner(false);
        app.run();
    }

    @PostConstruct
    public void foo() {
        System.out.println("Instantiated service name = " + service.serviceName);
    }
    }