干净的代码-@Autowired应该在哪里应用?
我将从一个简单的例子开始。您有一个Spring启动应用程序,该应用程序CommandLineRunner
在初始化时运行一个类。
// MyCommandLineRunner.javapublic 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中使用基于构造函数的依赖项注入。始终对强制性依赖项使用断言。
现在,如果我遵循这一点,我将有一个基于构造函数的依赖注入
@Autowiredpublic MyCommandLineRunner(DataSource ds) { ... }
这也意味着我也必须编辑Application.java
,因为构造函数需要一个参数。在Application.java
如果我尝试使用setter注入,我会得到相同的警告。如果我也重构它,我会得出一些讨厌的代码。
// MyCommandLineRunner.javapublic 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需要自动装配/初始化。它会报告错误,并且不会被编译。
回答:
有几种方法可以改善它。
您可以删除
@Autowired
从你的MyCommandLineRunner
,你是让一个@Bean
方法构建它的一个实例。注入DataSource
直接进入方法作为参数。或删除
@Autowired
并删除您@Bean
的@Component
注释,MyCommandLineRunner
并在其上打上注释,以检测到它并删除工厂方法。将
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());
}
}
和应用程序类。
@SpringBootApplicationpublic class Application {
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MyCommandLineRunner schedulerRunner(DataSource ds) {
return new MyCommandLineRunner(ds);
}
}
回答:
@Componentpublic 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());
}
}
和应用程序类。
@SpringBootApplicationpublic class Application {
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
}
回答:
@SpringBootApplicationpublic 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