干净的代码-@Autowired应该在哪里应用?

我将从一个简单的例子开始。您有一个Spring启动应用程序,该应用程序CommandLineRunner在初始化时运行一个类。

// MyCommandLineRunner.java

public class MyCommandLineRunner implements CommandLineRunner {

private final Log logger = LogFactory.getLog(getClass());

@Autowired //IntelliJ Warning

private DataSource ds;

@Override

public void run(String... args) throws Exception {

logger.info("DataSource: " + ds.toString());

}

}

// Application.java

@SpringBootApplication

public class Application {

public static void main(String... args) {

SpringApplication.run(Application.class, args);

}

@Bean

public MyCommandLineRunner schedulerRunner() {

return new MyCommandLineRunner();

}

}

现在,这样就可以了,一切都很好。但是,IntelliJ报告警告@Autowired位于何处(我在注释中标记了何处)

始终在bean中使用基于构造函数的依赖项注入。始终对强制性依赖项使用断言。

现在,如果我遵循这一点,我将有一个基于构造函数的依赖注入

@Autowired

public MyCommandLineRunner(DataSource ds) { ... }

这也意味着我也必须编辑Application.java,因为构造函数需要一个参数。在Application.java如果我尝试使用setter注入,我会得到相同的警告。如果我也重构它,我会得出一些讨厌的代码。

// MyCommandLineRunner.java

public class MyCommandLineRunner implements CommandLineRunner {

private final Log logger = LogFactory.getLog(getClass());

private DataSource ds;

@Autowired // Note that this line is practically useless now, since we're getting this value as a parameter from Application.java anyway.

public MyCommandLineRunner(DataSource ds) { this.ds = ds; }

@Override

public void run(String... args) throws Exception {

logger.info("DataSource: " + ds.toString());

}

}

// Application.java

@SpringBootApplication

public class Application {

private DataSource ds;

@Autowired

public Application(DataSource ds) { this.ds = ds; }

public static void main(String... args) {

SpringApplication.run(Application.class, args);

}

@Bean

public MyCommandLineRunner schedulerRunner() {

return new MyCommandLineRunner(ds);

}

}

上面的代码产生相同的结果,但是在IntelliJ中不报告任何警告。我很困惑,第二代码比第一代码好吗?我是否遵循错误的逻辑?这应该以不同的方式接线吗?

注意DataSource只是一个纯示例,此问题适用于所有自动接线的情况。

note 2

只能说MyCommandLineRunner.java不能有另一个空的构造函数,因为DataSource需要自动装配/初始化。它会报告错误,并且不会被编译。

回答:

有几种方法可以改善它。

  1. 您可以删除@Autowired从你的MyCommandLineRunner,你是让一个@Bean方法构建它的一个实例。注入DataSource直接进入方法作为参数。

  2. 或删除@Autowired并删除您@Bean@Component注释,MyCommandLineRunner并在其上打上注释,以检测到它并删除工厂方法。

  3. MyCommandLineRunner您的@Bean方法内联为lambda。

回答:

public class MyCommandLineRunner implements CommandLineRunner {

private final Log logger = LogFactory.getLog(getClass());

private final DataSource ds;

public MyCommandLineRunner(DataSource ds) { this.ds = ds; }

@Override

public void run(String... args) throws Exception {

logger.info("DataSource: " + ds.toString());

}

}

和应用程序类。

@SpringBootApplication

public class Application {

public static void main(String... args) {

SpringApplication.run(Application.class, args);

}

@Bean

public MyCommandLineRunner schedulerRunner(DataSource ds) {

return new MyCommandLineRunner(ds);

}

}

回答:

@Component

public class MyCommandLineRunner implements CommandLineRunner {

private final Log logger = LogFactory.getLog(getClass());

private final DataSource ds;

public MyCommandLineRunner(DataSource ds) { this.ds = ds; }

@Override

public void run(String... args) throws Exception {

logger.info("DataSource: " + ds.toString());

}

}

和应用程序类。

@SpringBootApplication

public class Application {

public static void main(String... args) {

SpringApplication.run(Application.class, args);

}

}

回答:

@SpringBootApplication

public class Application {

private static final Logger logger = LoggerFactory.getLogger(Application.class)

public static void main(String... args) {

SpringApplication.run(Application.class, args);

}

@Bean

public MyCommandLineRunner schedulerRunner(DataSource ds) {

return (args) -> (logger.info("DataSource: {}", ds);

}

}

所有这些都是构造实例的有效方法。使用哪一种,请使用自己喜欢的一种。还有更多选项(此处提到的所有变化)。

以上是 干净的代码-@Autowired应该在哪里应用? 的全部内容, 来源链接: utcz.com/qa/416717.html

回到顶部