Spring注解的区别

Posted

技术标签:

【中文标题】Spring注解的区别【英文标题】:Difference between Spring annotations 【发布时间】:2012-08-27 02:15:46 【问题描述】:

问题:

1) @Component@Configuration 的区别?

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

2)@Autowired@Inject@Resource有什么区别? - 什么时候使用? - 各自的优缺点是什么?

【问题讨论】:

见:***.com/a/41802044/2167531 【参考方案1】:

@Component@Configuration 确实是非常不同类型的注解。

@Component 和类似的注解(@Service@Repository 等)和它的 JSR-330 对应的 @Named 允许您声明要通过使用 <context:component-scan/> 或 @987654335 进行自动扫描来获取的 bean @它们为类注册bean定义,所以它们大致相当于在XML中用<bean ... />标签声明指定的bean。此 bean 类型将遵循标准代理创建策略。

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

示例来自documentation的 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 等价于 @Autowired@Autowired(required=true),但您无法使用 JSR-330 @Injectannotation 获得 @Autowired(required=false) 行为。此注解始终使用按类型自动装配。

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

示例 假设我们在容器中有一个名为 beanAlphaAlphaClass bean 和一个 BetaClass bean 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 注释时始终明确指定资源名称是一个好习惯。

文档

Spring annotations

Bean standard annotations

正如 shevchik 所指出的,

update 修复了 JSR 引用。 DI 特定注解由 Google(Guice Framework)和 SpringSource(Spring Framework)工程师开发的 JSR-330 提供。 @Resource 是基于 JNDI 的,由 JSR-250 提供。

【讨论】:

"@Named 和 @Inject" 是 JSR330 注释。 “@Resource、@PostConstruct、@PreDestroy”是 JSR250。【参考方案2】:

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

【讨论】:

如果这是真的,那么为什么它们似乎可以互换使用? 简洁明了 @Component@Configuration 本质上是相同的。我可以看到的主要区别是@Configuration 类上的任何@Bean 方法都将被记忆(在第一次执行时缓存,以便所有未来的请求只返回相同的对象而不执行该方法)。【参考方案3】:

在上面的大多数答案中,用户建议说@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。 实际执行明智似乎没有区别。

【讨论】:

配置和组件之间至少有一个区别。配置允许您的 Bean 具有 bean 间的依赖关系,而 Component 则没有。 docs.spring.io/spring/docs/current/spring-framework-reference/… @Configuration 类上的任何 @Bean 方法都将被记忆(在第一次执行时缓存,以便所有未来的请求只返回相同的对象而不执行该方法)。 @Components 的情况并非如此。他们的方法每次都会运行,每次都可能返回一个新对象(即使该对象可能是 .equals 与所有先前执行的返回值等效)。见:***.com/a/41802044/2167531【参考方案4】:

关于@Autowired@Inject@Resource 之间的区别,您可以查看here。在这里您可以进行全面的描述和比较。

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

@Component@Configuration 用途不同,因此比较它们没有意义。

【讨论】:

在您提到的链接中还指出,使用 @Configuration 注释类表明该类可以被 Spring IoC 容器用作 bean 定义的来源。所以我真的不明白它和@Component 有什么不同? 根据 Spring Java 文档,真正的区别在于 @Configuration 注释类 'inter-bean references' are guaranteed to respect scoping and AOP semantics(引用自 here)。在@Component 注释类scoping semantics are not respected ... for inter-bean method invocations in this mode 中。根据ticket,这种差异也没有得到很好的记录。【参考方案5】:

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

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

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

【讨论】:

以上是关于Spring注解的区别的主要内容,如果未能解决你的问题,请参考以下文章

Spring中@Autowired注解@Resource注解的区别(转)

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

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

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

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

Spring和Hibernate的注解整合 hibernate3和hibernate4/5的区别