Spring Bean 注释名称属性的用途是什么?

What is the purpose of the Spring Bean annotation name attribute?

我刚刚学习 spring,关于使用 name 属性作为字符串的注释配置,我感到非常奇怪。

@Bean(name = "com.my.injected.Service")
public InjectedService injectedService() {
    return injectedService;
}

此名称是否与 Spring Bean XML configuration id and class attributes 相似?

<bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
</bean>

为什么这不简单

@Bean(clazz = com.my.injected.Service.class)
public InjectedService injectedService() {
    return injectedService;
}

代替?

您在这两种情况下都完全限定了路径,并且实际上使用 class 使您的 IDE 更容易在您搞砸时告诉您。我知道 XML 配置最先出现,自然它总是按字符串查找东西,所以这只是一个保留吗?使用字符串是否有一些优势或使用 .class 的主要缺点?

问题最初是基于一个错误的前提。我对其进行了编辑,以阐明这个前提是什么,并让新来的人不那么困惑。希望我这样做是为了让给定的答案仍然完全适用;如果没有,我们深表歉意。

@Bean 注解是为了提供一个 spring bean。要提供的 bean 的类型将与您在 return 方法中定义的 class/interface 的类型相同。因此,不是在方法中向 return 声明一个具体的 class,而是 return 顶部(抽象)class/interface。

想象一下这种情况:

public interface MyEntityDao {
    MyEntity get(String id);
}

@Repository
public class MyEntityDaoDatabaseImpl implements MyEntityDao {
    @Override
    public MyEntity get(String id) {
        /* implementation that goes to database every time */
    }
}

@Repository
public class MyEntityDaoCacheImpl implements MyEntityDao {
    @Override
    public MyEntity get(String id) {
        /* implementation that looks the data
           up in cache, never in database */
    }
}

@Configuration
public class MyAppConfiguration {
    @Bean
    public MyEntityDaoDatabaseImpl method1() {
        return new MyEntityDaoDatabaseImpl();
    }
    @Bean
    public MyEntityDaoCacheImpl method2() {
        return new MyEntityDaoCacheImpl();
    }
}

@Service
public class MyEntityService {
    @Autowired //what to inject here?
    MyEntityDao dao;
}

在上述情况下,建议的接口有两种实现。除了名称之外,框架如何能够理解要使用哪个实现?

@Service
public class MyEntityService {
    @Autowired
    @Qualifier("properBeanNameToInject")
    MyEntityDao dao;
}

Bean 名称不一定与其 class 甚至它实现的任何接口相关。这是一个名字,仅此而已。当您使用注释配置时,Spring 计算出 class 或接口 @Bean 提供的确切内容,就像 java 代码的其余部分一样:通过完全限定名称代码或通过文件中指定的导入。在您的情况下,您可能在 java 文件的顶部有一个 import com.my.injected.Service; 语句。

您的示例使用完全限定的 class 名称作为 bean 名称。这是你的选择。您可以使用任何其他标识符。如果您的代码提供的对象的名称与您的代码必须包含或使用的另一个第 3 方 @Bean 对象完全相同,则使用完全限定名称可能很有用。但是,您可以轻松地使用 name = "myService".

bean 名称有助于 Spring(和应用程序程序员)区分同一 bean 的多个实例 class,因为您可以多次部署相同的 class 作为 bean。如果只出现一个 bean 类型的实例,则您不必手动为其命名:spring 默认情况下这样做。

如果您有多个具有相同类型或实现相同接口的 bean,并且您想要引用特定的 bean,请使用 @Qualifier 注释。