44

问题:

@Component1)和之间的区别@Configuration

我已经读过两者都消除了将代码放入 XML 中的必要性,但没有得到它们之间的区别。

@Autowired2 )@Inject和之间有什么区别@Resource
- 什么时候使用?
- 各自的优缺点是什么?

4

5 回答 5

56

@Component并且@Configuration确实是非常不同类型的注释。

@Component和类似的注解(@Service,@Repository等)及其对应的JSR-330@Named允许您声明要通过自动扫描获取的 bean, <context:component-scan/>或者@ComponentScan它们为类注册 bean 定义,因此它们大致相当于用XML 中的<bean ... />标记。此 bean 类型将遵守标准代理创建策略。

@Configurationannotation 被设计为 XML 配置文件的替换。为了创建带@Configuration注释的 bean,Spring 将始终使用CGLIB子类化带@Configuration注释的类,覆盖其@Bean带注释的方法以将其替换为 bean 查找方法,以使单例 bean 仅创建一次。(Spring 不CGLIB用于拦截普通Spring bean 的内部方法调用,而是创建一个单独的代理实例(与 JDK 代理相同)。这样做允许使用代理来避免基数不匹配 - 例如代理单例可以获取当前会话 bean,仅通过类继承是不可能的。)。尽管如此,带注释的类仍然可以使用带注释的(,@Configuration@Autowired@Inject等)从容器中请求 bean(甚至还有其他@Configuration带注释的 bean)的字段和属性。

来自文档4.12.5 部分的示例

@Configuration
public class AppConfig {

  @Bean
  public ClientService clientService1() {
    ClientServiceImpl clientService = new ClientServiceImpl();
    clientService.setClientDao(clientDao());
    return clientService;
  }
  @Bean
  public ClientService clientService2() {
    ClientServiceImpl clientService = new ClientServiceImpl();
    clientService.setClientDao(clientDao());
    return clientService;
  }

  @Bean
  public ClientDao clientDao() {
    return new ClientDaoImpl();
  }
}

在上面的示例中,只会创建一个ClientDao实例。

@Autowired是 Spring 注解,而@Inject是 JSR-330 注解。 @Inject等效于@Autowiredor @Autowired(required=true),但您无法@Autowired(required=false)使用 JSR-330@Inject注释获得行为。此注释始终使用按类型自动装配。

Spring 以一种相当特殊的方式实现JSR-250 @Resource注释。@Resource最初是为在 Java EE 中定位 JNDI 资源而设计的,但 Spring 扩大了它的适用性,使其可以连接到容器中的任何 bean(JNDI 资源在SimpleJndiBeanFactory的帮助下作为 bean 可用)。对应bean的名称可以指定为注解的name属性@Resource,如果没有指定名称,则使用被注解的字段或属性的名称。另一个奇怪的特性是,如果没有找到具有属性名称的 bean,spring 将回退到按类型布线。

示例 假设我们在容器中有一个AlphaClass名为beanAlpha的 bean和一个BetaClassbean beanBeta

@Resource 
BetaClass something;  // Wires to beanBeta - by-type

@Resource 
BetaClass beanAlpha;  // Will throw exception, because "beanAlpha" is not BetaClass -> it's a bad idea to use @Resource as a replacement of @Autowired

@Resource 
Object beanAlpha;  //Wires to beanAlpha - by-name

因此,在使用@Resource注释时始终明确指定资源名称是一个好习惯。

文档

弹簧注解

Bean标准注解

正如shevchik所指出的,更新固定的 JSR 引用。DI 特定注解由 Google(Guice Framework)和 SpringSource(Spring Framework)工程师开发的 JSR-330 提供。@Resource是基于 JNDI 并由JSR-250提供的。

于 2012-09-01T20:06:35.343 回答
22

@Component等价于<bean>
@Configuration等价于<beans>

于 2012-09-02T03:59:22.040 回答
5

在上面的大多数答案中,用户建议说@Component 和@Configuration 用于不同的目的。但我没有看到它在现实中发生。

但我有一个简单的 Spring MVC 应用程序。

@Configuration
    public class SpringConfiguration {

@Bean
public  InternalResourceViewResolver initViewResolver(){
    InternalResourceViewResolver x = new InternalResourceViewResolver();
    x.setPrefix("/WEB-INF/jsp/");
    x.setSuffix(".jsp");
    return x;
}

}

即使这个主类被注释为@Component 而不是@Configuration,它也能正常工作。

类似地,如果您有使用@Bean 注释的方法,则在注释为@Component 的类中,这些bean 是在加载上下文时创建的。

所以我认为,只是为了代码的可读性,我们应该将主配置类标记为@Configuration,其他类使用@Component。实际执行明智似乎没有区别。

于 2012-11-04T10:11:40.653 回答
2

关于两者的区别@Autowired,你可以看这里。在这里您可以进行详尽的描述和比较。@Inject@Resource

与第一个区别有关的@Configuration是:用作XML基于 - 的配置的替代品,即。它将类标记为用于Java基于配置的类,请参见此处。反过来,@Component实际上用于将类标记为要实例化的类,Spring并由注释@Configuration进行元@Component注释。

@Component@Configuration服务于不同的目的,因此比较它们没有意义。

于 2012-09-01T16:14:27.643 回答
2

1) 如果您想要 XML 配置,则忽略 @Configuration,因为这仅对基于 Java 的配置有用。XML 配置可能最适合不熟悉 Spring 的人,因为有更多示例可用。

@Component 注解的类在组件扫描期间被拾取。使用它们来标记您想要作为 Spring bean 公开的类。同样,您可以在 XML 配置中声明所有 bean 并完全忽略 @Component。

2) 如果您乐于将应用程序绑定到 Spring,请使用 @Autowire 而不是 javax 等效的 @Inject。我建议接受对 Spring 的依赖是最好的开始方式。

于 2012-09-02T08:31:18.477 回答