我已经看到所有关于弹簧自动接线配置为空的问题,而且我似乎无法弄清楚。因此,我将其简化为一个小问题,希望有人能提供帮助。
Hello.java
package hello;
@SpringBootApplication
public class Hello {
private static final Logger log = LoggerFactory.getLogger(Hello.class);
@Autowired
private AppConfig appConfig;
public void start() {
log.info("Start");
log.info("AppConfig: {}", appConfig);
}
public static void main(String args[]) {
SpringApplication.run(Hello.class, args).close();
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
Hello hello = new Hello();
hello.start();
};
}
}
AppConfig.java
package hello;
@Configuration
public class AppConfig {
@Value("${string.test:bob}")
private String commandLineArg;
public String getCommandLineArg() {
return commandLineArg;
}
}
运行此功能!但是,它将null
变量记录在appConfig
中。从我的角度来看,它应该已经自动实例化并填写了。这是怎么回事?
答案 0 :(得分:1)
在您的commandLineRunner中,您自己实例化了“ Hello”(新的Hello()),因此您的“ hello”对象在Spring之前不是托管Bean,因此它根本没有依赖项注入。
您这样做有什么特殊原因吗? Spring将通过@ SpringBootApplication-Annotation实例化Hello。在您的CommandLineRunner中,只需调用“ start()”,即可自动关联您的依赖项:
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
start();
};
}
如果CommandLineRunner正在从另一个类运行,则可以通过以下方式获取Spring管理的“ Hello”实例:
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
Hello foo = ctx.getBean(Hello.class);
foo.start();
};
}
答案 1 :(得分:1)
Hello hello = new Hello(); // Creates new Hello instance, not managed by Spring container
改为使用:
package com.example.demo;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
}
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class DemoApplication {
@Autowired
AppConfig appConfig;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public void start() {
System.out.println("Start");
System.out.println("AppConfig: {}" + appConfig);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
this.start();
};
}
}
输出:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.4.RELEASE)
2019-04-14 12:22:49.515 INFO 7892 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on sparrow with PID 7892 (/home/anant/Downloads/demo/target/classes started by anant in /home/anant/Downloads/demo)
2019-04-14 12:22:49.519 INFO 7892 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-04-14 12:22:50.446 INFO 7892 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.383 seconds (JVM running for 1.875)
Start
AppConfig: {}com.example.demo.AppConfig$$EnhancerBySpringCGLIB$$9ca35f67@68f1b17f
答案 2 :(得分:1)
在CommandLineRunner bean中,您正在创建Hello的新实例,并在其上调用start。您好实例不是Spring bean,因此自然不会注入任何依赖项。要使其正常工作,只需在您的CommandLineRunner
bean中调用start(),CommandLineRunner
在应用程序上下文填充并准备就绪后运行:
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> start();
}
或者,您可以在start()方法上添加@PostConstruct
以便在Spring应用程序上下文中填充bean之后运行:
@PostConstruct
public void start() {
log.info("Start");
log.info("AppConfig: {}", appConfig);
}