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

2024-06-24

我将从一个简单的例子开始。你有一个 Spring boot 应用程序运行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();
    }
}

现在,就像这样,这行得通,一切都OK了。然而,IntelliJ 报告了一个警告,其中@Autowired位于(我在评论中标记了位置)

Spring团队推荐:始终在 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 中报告任何警告。 我很困惑,第二个代码比第一个代码好在哪里?我是否遵循了错误的逻辑?这应该以不同的方式连接吗?

简而言之,正确的方法是什么?

note DataSource只是一个纯粹的例子,这个问题适用于自动连接的任何东西。

note 2只是想说MyCommandLineRunner.java不能有另一个空的构造函数,因为 DataSource 需要自动装配/初始化。会报错,不会编译。


有几种方法可以改进它。

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

  2. 或者删除@Autowired并删除@Bean并打一巴掌@Component注释在你的MyCommandLineRunner检测到它并删除工厂方法。

  3. 内联您的MyCommandLineRunner在你的里面@Bean方法作为 lambda。

中没有自动装配MyCommandLineRunner

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

@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); 
    }

}

Inline CommandLineRunner

@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); 
    }
}

所有这些都是构建实例的有效方法。使用哪一种,使用你觉得舒服的那种。还有更多选项(此处提到的选项的所有变体)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

干净的代码 - @Autowired 应该应用在哪里? 的相关文章

随机推荐

  • Angularjs ui 路由器。如何重定向到登录页面

    我有4个状态 仪表板 仪表板 main 仪表板 次要 login 仪表板是抽象的 它是 minor 和 main 状态的父状态 下面是我的代码 state dashboard url dashboard abstract true temp
  • servlet 过滤器中的弹簧注入[重复]

    这个问题在这里已经有答案了 我正在尝试对 servlet 过滤器进行 spring 注入 该过滤器是引用的 jar 文件的一部分 所以 我无法将其更改为拦截器 在我的插件项目的 web xml 中
  • C++ 指向重载函数的指针

    我正在尝试使用 boost python 公开重载函数 函数原型是 define FMS lvl2 DLL API declspec dllexport void FMS lvl2 DLL API write const char key
  • 如何从 R 中的列表创建自动文本文件?

    如果我有包含多个数据帧的列表元素 并且我想将它们作为单独的文本文件写入磁盘上 名称为 NP1 NP2 NP3 我该怎么做 我使用了以下内容 lapply lst1 write table 但这并不能解决问题 我该怎么做 谢谢 这里有两种方法
  • 在 Postgres 中手动对列进行排序的正确方法是什么?

    我有一个用于开票的 SaaS 宠物项目 在其中 我希望我的客户每个都以票号 1001 开始 显然 我不能在 Postgres 中使用简单的自动字段 只需在值上添加 1000 因为我的所有客户将共享相同的数据库和相同的数据 tickets表
  • WPF DataGrid 双向绑定

    我有财产UserSet其中包含来自ObservableCollection
  • 使用 PHP 修改 HTML 标签元素

    我一直在尝试修改 HTML 标签元素 我有一个巨大的 HTML 文件列表需要修改 我需要删除图像和以下文本之间的线条 我正在使用 PHP 我使用 DOMDocument 来访问所有节点 并且还可以获得节点路径 但我无法从节点路径修改该特定的
  • Prolog - DCG 解析器,带有来自文件的输入

    作为项目的一部分 我需要编写一个解析器 它可以读取文件并解析为我可以在程序中使用的事实 文件结构如下所示 property el1 el2 我最终想要的是 property el1 property el2 我这样读我的文件 main op
  • 数据库设计 - 类别和子类别[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我需要在类似于黄金页面的东西上实现分类和子分类 假设我有下表 类别表 CategoryId Title 10 Home 20 Business
  • 无法将 int 字段设置为空值

    我有这个int column Column length 4 private int contract owner id 我不需要为每个表行设置始终值 当我进行选择查询时 出现此异常 Can not set int field org en
  • Javascript:让主体加载函数等待脚本完成

    我正在调用一些函数 它们需要一些时间 毫秒 但我不希望在这些函数完成之前显示页面 现在 我可以看出页面已加载 然后脚本最终完成 现在 我正在调用主体中的函数 onload 另外 我可能遇到的另一个问题是我需要访问 html 内容中的 div
  • Java:支持宏吗?

    我只是好奇人们如何解决这个问题 我经常一直编写相同类型的代码 例如 new Thread Change this line start 我不断更改显示 更改此行 的行 然后启动一个线程 这一变化可以是一行或几行 我将如何压缩这段代码 好吧
  • 如何将许多 numpy 文件逐个文件放入一个大 numpy 文件中?

    我有 166600 个 numpy 文件 我想将它们放入一个 numpy 文件中 逐个文件 我的意思是 我的新大文件的创建必须从头开始 第一个文件必须在文件中读取和写入 因此大文件只包含第一个文件 之后我需要读取和写入第二个文件 所以大文件
  • docker 服务更新与使用现有堆栈部署 docker 堆栈

    在部署了一组服务后 我对使用 docker swarm 模式命令来更新现有服务有疑问docker stack deploy 据我了解 每个服务在创建时都固定到图像的 SHA256 摘要 因此 如果您重建并推送图像 具有相同标签 并且尝试运行
  • 如何在swings中组合jtable中的两个列标题

    我需要在 swing 中制作一个像这样的 gui 你能帮我吗 有什么方法可以按列和行组合列标题 所以你想要多标题行jtable 您必须对标题进行分组 GroupableHeaderExample java public class Grou
  • 以不可检测的方式检查 WebSocket 帧

    如何以页面无法检测到的方式在 Chrome 扩展程序或 Firefox 附加组件中读取网页的 WebSocket 框架 从 Chrome 开发工具扩展检查 WebSockets 帧 https stackoverflow com quest
  • HOC 中的样式化组件

    我想使用高阶组件将样式添加到我的组件包装器中 打字稿说有错误ComponentWithAdddedColors type Props bg string function withColors
  • 将 Symfony2 服务配置移至捆绑包

    我的 config yml 中有以下内容 services my user provider class Acme MySecurityBundle Security UserProvider 但想将其移至我的 config ymlMySe
  • 机车滚动在我的 Nuxt3 项目中不起作用

    我正在使用机车滚动和 nuxt3 这是我的回购协议 https github com cyprianwaclaw nuxt git https github com cyprianwaclaw nuxt git 我导入了async loco
  • 干净的代码 - @Autowired 应该应用在哪里?

    我将从一个简单的例子开始 你有一个 Spring boot 应用程序运行CommandLineRunner初始化时的类 MyCommandLineRunner java public class MyCommandLineRunner im