使用@Autowired 时什么时候必须创建新实例
When do I have to create new instance while using @Autowired
直到今天,我都 100% 确定在将 class 定义为 bean 时不必创建新实例。
今天有点懵
我会尽量用文字解释其中的一部分,因为我认为上传所有代码会让人难以理解。
我使用 intellij 和 Spring 创建了新的 REST 项目。
我创建了新的 class 映射并向其添加了 @RestController
。
在此 class 中,我添加了我自己创建的另一个 class 的 属性,并向其中添加了 @Autowired
。
我从未创建此 class 的新实例,但我确实添加了一个 bean 配置。
到现在为止一切正常。
我想添加 ThreadPoolTaskScheduler
逻辑,所以我打开了新的 class,添加了新的 属性 ThreadPoolTaskScheduler
并用 @Autowired
标记。
我为它添加了一个Bean:
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
ThreadPoolTaskScheduler threadPoolTaskScheduler
= new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix(
"ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
现在主要 class 如果我不发送 class 的新实例 if 将抛出 null 异常。
因此此代码有效:
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 class:
@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,它工作正常,为什么我必须这样做? spring 能处理所有事情还是什么都不处理?
如果你想让我添加更多代码,请告诉我。
您可以获得像这样的 bean 对象:
public class RestApiApplication{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(RestApiApplication.class, args);
TaskScheduler ts = context.getBean(TaskScheduler.class);
ts.setTaskScheduler()
}
}
但在实际项目中使用 ApplicationContext
就像这个例子是个坏主意!
如果你需要 REST,你应该使用 @RestController 注释。
检查这个 guide
当您实例化一个 bean 本身时,它不会再对其进行管理,因此将不会处理所有 @Autowired
依赖项。为了确保正确注入依赖项,您需要通过 Spring 上下文实例化 bean。 Spring 需要实例化整个 beans trail 才能正确执行依赖注入。请检查此 link 中的 IoC 详细信息:https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-class-ctor
查看您的代码,有两种方法可以做到这一点
使用Spring引导
将具有 main 方法的 class 将如下所示:
@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 实例,如果您需要执行一些 integration/unit 测试,这种方法效果很好。
直到今天,我都 100% 确定在将 class 定义为 bean 时不必创建新实例。 今天有点懵
我会尽量用文字解释其中的一部分,因为我认为上传所有代码会让人难以理解。
我使用 intellij 和 Spring 创建了新的 REST 项目。
我创建了新的 class 映射并向其添加了 @RestController
。
在此 class 中,我添加了我自己创建的另一个 class 的 属性,并向其中添加了 @Autowired
。
我从未创建此 class 的新实例,但我确实添加了一个 bean 配置。
到现在为止一切正常。
我想添加 ThreadPoolTaskScheduler
逻辑,所以我打开了新的 class,添加了新的 属性 ThreadPoolTaskScheduler
并用 @Autowired
标记。
我为它添加了一个Bean:
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
ThreadPoolTaskScheduler threadPoolTaskScheduler
= new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix(
"ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
现在主要 class 如果我不发送 class 的新实例 if 将抛出 null 异常。
因此此代码有效:
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 class:
@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,它工作正常,为什么我必须这样做? spring 能处理所有事情还是什么都不处理?
如果你想让我添加更多代码,请告诉我。
您可以获得像这样的 bean 对象:
public class RestApiApplication{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(RestApiApplication.class, args);
TaskScheduler ts = context.getBean(TaskScheduler.class);
ts.setTaskScheduler()
}
}
但在实际项目中使用 ApplicationContext
就像这个例子是个坏主意!
如果你需要 REST,你应该使用 @RestController 注释。 检查这个 guide
当您实例化一个 bean 本身时,它不会再对其进行管理,因此将不会处理所有 @Autowired
依赖项。为了确保正确注入依赖项,您需要通过 Spring 上下文实例化 bean。 Spring 需要实例化整个 beans trail 才能正确执行依赖注入。请检查此 link 中的 IoC 详细信息:https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-class-ctor
查看您的代码,有两种方法可以做到这一点
使用Spring引导
将具有 main 方法的 class 将如下所示:
@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 实例,如果您需要执行一些 integration/unit 测试,这种方法效果很好。