我何时必须在使用@Autowired

时间:2018-12-13 13:50:24

标签: java spring intellij-idea 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());
    }
}
  1. 我想不通setTaskScheduler的threadPoolTask​​Scheduler获得NULL的原因,知道吗?
  2. 如果我也将TaskScheduler定义为可以正常工作的bean,为什么必须这样做?春天能应付一切还是什么?

如果您要我添加更多代码,请告诉我。

2 个答案:

答案 0 :(得分:1)

当实例化一个bean本身时,它不再使其受管理,因此将不处理所有@Autowired依赖项。为了确保正确注入依赖项,您将需要通过Spring上下文实例化Bean。为了正确执行依赖注入,Spring需要实例化整个bean路径。请检查此链接中的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实例,如果您需要执行一些集成/单元测试,则可以很好地工作。

答案 1 :(得分:0)

您可以像这样获得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