首页 > 解决方案 > @Autowired 注解没有弹簧启动

问题描述

我正在开发一个 JAR 文件,该文件每天只在容器中运行一次,因此它不需要 Spring 引导功能。

但仍然要利用spring的特性,我有一个应用程序配置这种方式

@Configuration
@ComponentScan("com.arun.fp")
public class ApplicationConfig {

}

然后这是我的主要课程,绝对可以正常工作

package com.arun.fp;

import com.arun.fp.utils.JobUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.time.Instant;


public class JobMain {

    

    private ApplicationContext applicationContext;

    public JobMain(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public static void main(String... args) {
        var applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        new JobMain(applicationContext).startJob();
    }

    public void startJob() {
        var jobUtils = applicationContext.getBean(JobUtils.class);
        var jobId = jobUtils.generateJobId();
        try {
            System.out.println(" -------------- ");

            var startTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Started at " + startTime);

           /* var fileProcessingJob = new FileProcessorJob();
            fileProcessingJob.startProcess();*/

            Thread.sleep(2000);

            var endTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Ended at " + endTime);
            var duration = jobUtils.getJobDurationInSeconds(startTime, endTime);
            System.out.println("Job with ID: " + jobId + " took " + duration + " seconds to complete the job");
        } catch (Exception exception) {
            
        }


    }


}

但不是得到applicationContext.getBean(..)并尝试使用@Autowired这样的注释

@Autowired
private JobUtils jobUtils;

但它不是自动装配的,而且只会为空..

@Autowired只能用于 Spring Boot 应用程序吗?不适用于使用 spring 的 java 应用程序?

标签: javaspring

解决方案


当然可以使用@Autowired,但由于您JobMain不是 Spring bean,因此它当然不会自动装配。基本上这是重复的更多原因在这里

所以要修复你JobMain的 an@Component并且不要自己构建一个新实例。

import java.time.Instant;

@Component
public class JobMain {  

  @Autowired
  private JobUtils jobUtils;

  public static void main(String... args) {
    new AnnotationConfigApplicationContext(ApplicationConfig.class);        
  }

  @PostConstruct // actually you are better of using a listener for instance.
 public void startJob() {
   var jobId = jobUtils.generateJobId();
   try {
          System.out.println(" -------------- ");

            var startTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Started at " + startTime);

           /* var fileProcessingJob = new FileProcessorJob();
            fileProcessingJob.startProcess();*/

            Thread.sleep(2000);

            var endTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Ended at " + endTime);
            var duration = jobUtils.getJobDurationInSeconds(startTime, endTime);
            System.out.println("Job with ID: " + jobId + " took " + duration + " seconds to complete the job");
        } catch (Exception exception) {
            
        }
    }
}

但是,正如我在评论中已经提到的,没有什么可以阻止您将 Spring Boot 用于 CLI 应用程序。只是不要包含网络内容,它会做你想做的事(开始工作,完成后会停止)。

假设您JobMain在其中,com.arun.fp您可以执行以下操作。

  1. 放弃你的ApplicationConfig课程(这不是必需的)。
  2. 修改你JobMain的 Spring Boot
  3. 用作spring-boot-starter依赖项
  4. 打包应用程序
  5. 运行java -jar your-job.jar(它现在将开始,完成工作并完成)。
@SpringBootApplication
public class JobMain {  

  public static void main(String... args) {
    SpringApplication.run(JobMain.class, args);      
  }

  @Bean
  public CommandLineRunner jobRunner(JobUtils jobUtils) {

    return (args) -> {
        var jobId = jobUtils.generateJobId();
        try {
            System.out.println(" -------------- ");

            var startTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Started at " + startTime);

           /* var fileProcessingJob = new FileProcessorJob();
            fileProcessingJob.startProcess();*/

            Thread.sleep(2000);

            var endTime = Instant.now();
            System.out.println("Job with ID: " + jobId + " Ended at " + endTime);
            var duration = jobUtils.getJobDurationInSeconds(startTime, endTime);
            System.out.println("Job with ID: " + jobId + " took " + duration + " seconds to complete the job");
        } catch (Exception exception) {
            
        }
    }
}

这将启动作业,因为CommandLineRunner将在所有 bean 启动后执行。当CommandLineRunner完成它的工作时,应用程序将停止,因为没有更多的进程保持活动。


推荐阅读