Spring @Autowired 是按名称还是按类型注入 bean?

Posted

技术标签:

【中文标题】Spring @Autowired 是按名称还是按类型注入 bean?【英文标题】:Does Spring @Autowired inject beans by name or by type? 【发布时间】:2015-08-02 08:16:52 【问题描述】:

我正在阅读《初春》(威利出版社)的书。在第 2 章中有一个例子 关于 Java 配置和@Autowired。它提供了这个@Configuration

@Configuration
public class Ch2BeanConfiguration 

    @Bean
    public AccountService accountService() 
        AccountServiceImpl bean = new AccountServiceImpl();
        return bean;
    

    @Bean
    public AccountDao accountDao() 
        AccountDaoInMemoryImpl bean = new AccountDaoInMemoryImpl();
        //depedencies of accountDao bean will be injected here...
        return bean;
    

    @Bean
    public AccountDao accountDaoJdbc() 
        AccountDaoJdbcImpl bean = new AccountDaoJdbcImpl();
        return bean;
    

还有这个普通的 bean 类

public class AccountServiceImpl implements AccountService 

    @Autowired
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) 
        this.accountDao = accountDao;
    
    ...

当我运行代码时,它可以工作。但我预计会出现异常,因为我在配置中定义了 2 个具有相同类型的 bean。

我意识到它是这样工作的:

如果 Spring 遇到多个具有相同类型的 bean,它会检查字段名称。 如果找到具有目标字段名称的 bean,则会将该 bean 注入到该字段中。

这不是错的吗? Spring 对 Java 配置的处理是否存在错误?

【问题讨论】:

我完全理解你为什么对此感到困惑——因为it's bad design, IMO。 【参考方案1】:

documentation 解释了这一点

对于后备匹配,bean 名称被视为默认限定符 value. 因此,您可以使用 id “main”而不是 嵌套限定符元素,导致相同的匹配结果。 但是,尽管您可以使用此约定来指代特定的 bean 的名字,@Autowired 基本上是关于类型驱动的注入 带有可选的语​​义限定符。这意味着限定符值, 即使使用 bean 名称后备,也总是具有缩小语义 在类型匹配集中;他们没有在语义上表达 引用一个唯一的 bean id

所以,不,这不是错误,这是预期的行为。如果按类型自动装配未找到单个匹配的 bean,则 bean id(名称)将用作后备。

【讨论】:

IMO 这是一个非常危险和糟糕的设计。注入资源的名称应该与该注入的注册方式无关。现在,所有事物都是通过字段名称耦合的?类应该可以随意命名变量/字段,而不考虑 DI。在设计课程时,DI 应该是“幕后”,而不是前台和中心。我也不同意 @Autowired 注释在课堂上的任何位置。同样,DI 应该是预先考虑并在应用程序级别进行初始化的。更下游的类应该没有 DI 的概念。

以上是关于Spring @Autowired 是按名称还是按类型注入 bean?的主要内容,如果未能解决你的问题,请参考以下文章

@Resource@Autowired等几个注解的区别

@Resource@Autowired等几个注解的区别

显示记录是按名称还是 EmpID 查找的

@Autowired的作用

关于@Autowired使用注意点

Spring中@Autowired注解@Resource注解的区别