java - 使用@Autowired 时我什么时候必须创建新实例
问题描述
直到今天,我 100% 确信在将类定义为 bean 时不必创建新的类实例。今天我有点糊涂了。
我将尝试用文字解释其中的一部分,因为我认为上传所有代码会让人难以理解。
我使用 intellij 和 Spring 创建了新的 REST 项目。我创建了映射它的新类并添加@RestController
到它。在这个类中,我添加了我自己创建并添加@Autowired
到其中的另一个类的属性。我从未创建过此类的新实例,但我确实添加了一个 bean 配置。直到现在一切正常。
我想添加ThreadPoolTaskScheduler
逻辑,所以我打开了新类,添加了新属性ThreadPoolTaskScheduler
并用@Autowired
.
我为它添加了一个 Bean:
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
ThreadPoolTaskScheduler threadPoolTaskScheduler
= new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix(
"ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
现在在主类中,如果我不发送类的新实例,如果会抛出空异常。
所以这段代码有效:
public static void main(String[] args) {
SpringApplication.run(RestApiApplication.class, args);
TaskScheduler taskScheduler = new TaskScheduler(new ThreadPoolTaskScheduler());
taskScheduler.setTaskScheduler();
}
而这段代码不是:
public static void main(String[] args) {
SpringApplication.run(RestApiApplication.class, args);
TaskScheduler taskScheduler = new TaskScheduler();
taskScheduler.setTaskScheduler();
}
这是 TaskScheduler 类:
@Controller
public class TaskScheduler {
@Autowired
ThreadPoolTaskScheduler threadPoolTaskScheduler;
TaskScheduler(){}
TaskScheduler(ThreadPoolTaskScheduler threadPoolTaskScheduler){
this.threadPoolTaskScheduler = threadPoolTaskScheduler;
}
public void setTaskScheduler(){
threadPoolTaskScheduler.schedule(
new ScheduledTask(),
new Date());
}
}
- 我无法弄清楚 setTaskScheduler 的 threadPoolTaskScheduler 为 NULL 的原因,知道吗?
- 如果我也将 TaskScheduler 定义为 bean,它可以正常工作,为什么我必须这样做?春天可以处理一切还是什么都没有?
如果您希望我添加更多代码,请告诉我。
解决方案
当您实例化一个 bean 本身时,它不再对其进行管理,因此@Autowired
不会处理所有依赖项。为了确保正确注入依赖项,您需要通过 Spring 上下文实例化 bean。Spring 需要实例化整个 bean trail 才能正确执行依赖注入。请查看此链接中的 IoC 详细信息:https ://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-class-ctor
查看您的代码,有两种方法可以做到这一点
使用 Spring Boot
将具有 main 方法的类将如下所示:
@SpringBootApplication
public class RestApiApplication implements CommandLineRunner {
@Autowired
private TaskScheduler ts;
public static void main(String[] args) {
SpringApplication.run(RestApiApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
ts.<your-code>
}
}
另一种方法是使用 ApplicationContext 直接获取 bean 实例,如果您需要执行一些集成/单元测试,这种方法效果很好。
推荐阅读
- sql-server - 无法将 Char 转换为货币
- mysql - AWS RDS - 错误:尝试使用 sequelize-cli 迁移时,用户 'geornalAdmin'@'%' 拒绝访问数据库 'mysql'
- python - 当 x 和 y 轴为文本 matplotlib 时注释数据点
- r - 三次根行为 R
- selenium-webdriver - Selenium/TestNG:正确的基础测试类设计
- python - 如何在 tensorflow 2.0 中使用预制的密集层进行训练?
- java - 如何让 ThreadPoolExecutor 在 Java 中立即执行
- java - 对字符串中的字符进行计数的函数
- javascript - 将 KMZ 文件输入到 Leaflet 地图中
- kubernetes - 如何在 2 个或多个 pod 之间共享一个 EBS 卷(只有一个会写,其余的只会读)?