【发布时间】:2012-08-27 02:15:46
【问题描述】:
问题:
1) @Component 和 @Configuration 的区别?
我已经读到两者都消除了将接线代码放入 XML 的必要性,但没有得到它们之间的区别。
2)@Autowired、@Inject和@Resource有什么区别?
- 什么时候使用?
- 各自的优缺点是什么?
【问题讨论】:
标签: java spring spring-annotations
问题:
1) @Component 和 @Configuration 的区别?
我已经读到两者都消除了将接线代码放入 XML 的必要性,但没有得到它们之间的区别。
2)@Autowired、@Inject和@Resource有什么区别?
- 什么时候使用?
- 各自的优缺点是什么?
【问题讨论】:
标签: java spring spring-annotations
@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 将回退到按类型布线。
示例
假设我们在容器中有一个名为 beanAlpha 的 AlphaClass 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 注释时始终明确指定资源名称是一个好习惯。
文档
正如 shevchik 所指出的,update 修复了 JSR 引用。 DI 特定注解由 Google(Guice Framework)和 SpringSource(Spring Framework)工程师开发的 JSR-330 提供。 @Resource 是基于 JNDI 的,由 JSR-250 提供。
【讨论】:
@Component 等价于<bean>,@Configuration 等价于<beans>。
【讨论】:
@Component 和 @Configuration 本质上是相同的。我可以看到的主要区别是@Configuration 类上的任何@Bean 方法都将被记忆(在第一次执行时缓存,以便所有未来的请求只返回相同的对象而不执行该方法)。
在上面的大多数答案中,用户建议说@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。 实际执行明智似乎没有区别。
【讨论】:
@Configuration 类上的任何 @Bean 方法都将被记忆(在第一次执行时缓存,以便所有未来的请求只返回相同的对象而不执行该方法)。 @Components 的情况并非如此。他们的方法每次都会运行,每次都可能返回一个新对象(即使该对象可能是 .equals 与所有先前执行的返回值等效)。见:stackoverflow.com/a/41802044/2167531
【讨论】:
1) 如果您需要 XML 配置,请忽略 @Configuration,因为这仅对基于 Java 的配置有用。 XML 配置可能最适合不熟悉 Spring 的人,因为有更多示例可用。
@Component 注释类在组件扫描期间被拾取。使用它们来标记您想要作为 Spring bean 公开的类。同样,您可以在 XML 配置中声明所有 bean,完全忽略 @Component。
2) 如果您愿意将您的应用程序绑定到 Spring,那么请使用 @Autowire 而不是 javax 等效的 @Inject。我建议接受对 Spring 的依赖是最好的开始方式。
【讨论】: