`

Spring Injection with @Resource, @Autowired and @Inject(转)

 
阅读更多

Overview

I’ve been asked several times to explain the difference between injecting Spring beans with ‘@Resource’, ‘@Autowired’, and ‘@Inject’. While I received a few opinions from colleagues and read a couple of posts on this topic I didn’t feel like I had a complete picture.

Annotations

Annotation Package Source
@Resource javax.annotation Java
@Inject javax.inject Java
@Qualifier javax.inject Java
@Autowired org.springframework.bean.factory Spring



In order to explore the behavior of each annotation I fired up Spring Tool Suite and started debugging the code. I used Spring 3.0.5.RELEASE in my research. The following is a summary of my findings.

The Code

I wanted to know how ‘@Resource’, ‘@Autowired’, and ‘@Inject’ resolved dependencies. I created an interface called ‘Party’ and created two implementations classes. This allowed me to inject beans without using the concrete type. This provided the flexibility I needed to determine how Spring resolves beans when there are multiple type matches.

public interface Party {
 
}

‘Person’ is a component and it implements ‘Party’.

package com.sourceallies.person;
...
@Component
public class Person implements Party {
 
}

‘Organization’ is a component and it implements ‘Party’.

package com.sourceallies.organization;
...
@Component
public class Organization implements Party {
 
}

I setup a Spring context that scans both of these packages for beans marked with ‘@Component’.

<context:component-scan base-package="com.sourceallies.organization"/>
<context:component-scan base-package="com.sourceallies.person"/>

Tests

Test 1: Ambiguous Beans

In this test I injected a ‘Party’ bean that has multiple implementations in the Spring context.

@Resource
private Party party;
@Autowired
private Party party;
@Inject
private Party party;

In all three cases a ‘NoSuchBeanDefinitionException’ is thrown. While this exception’s name implies that no beans were found, the message explains that two beans were found. All of these annotations result in the same exception.

org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No unique bean of type [com.sourceallies.Party] is defined: 
expected single matching bean but found 2: [organization, person]

Test 2: Field Name

In this test I named the Party field person. By default beans marked with ‘@Component’ will have the same name as the class. Therefore the name of the class ‘Person’ is person.

@Resource
private Party person;
@Autowired
private Party person;
@Inject
private Party person;

‘@Resource’ can also take an optional ‘name’ attribute. This is equivalent to the ‘@Resource’ code above. In this case the field variable name remains ‘party’. There is no equivalent syntax for ‘@Autowired’ or ‘@Inject’. Instead you would have to use a ‘@Qualifier’. This syntax will be covered later.

@Resource(name="person")
private Party party;

All four of these styles inject the ‘Person’ bean.

Test 3: Field Type

In this test I changed the type to be a ‘Person’.

@Resource
private Person party;
@Autowired
private Person party;
@Inject
private Person party;

All of these annotations inject the ‘Person’ bean.

Test 4: Default Name Qualifier

In this test I use a ‘@Qualifier’ annotation to point to the default name of the ‘Person’ component.

@Resource
@Qualifier("person")
private Party party;
@Autowired
@Qualifier("person")
private Party party;
@Inject
@Qualifier("person")
private Party party;

All of these annotations inject the ‘Person’ bean.

Test 5: Qualified Name

I added a ‘@Qualifier’ annotation to the ‘Person’ class

package com.sourceallies.person;
...
@Component
@Qualifier("personBean")
public class Person implements Party {
 
}

In this test I use a ‘@Qualifier’ annotation to point to the qualified name of the ‘Person’ component.

@Resource
@Qualifier("personBean")
private Party party;
@Autowired
@Qualifier("personBean")
private Party party;
@Inject
@Qualifier("personBean")
private Party party;

All of these annotations inject the ‘Person’ bean.

Test 6: List of Beans

In this test I inject a list of beans.

@Resource
private List<Party> parties;
@Autowired
private List<Party> parties;
@Inject
private List<Party> parties;

All of these annotations inject 2 beans into the list. This can also be accomplished with a ‘@Qualifier’. Each bean marked with a specific qualifier will be added to the list.

Test 7: Conflicting messages

In this test I add a bad ‘@Qualifier’ and a matching field name.

@Resource
@Qualifier("bad")
private Party person;
@Autowired
@Qualifier("bad")
private Party person;
@Inject
@Qualifier("bad")
private Party person;

In this case the field marked with ‘@Resource’ uses the field name and ignores the ‘@Qualifier’. As a result the ‘Person’ bean is injected.

However the ‘@Autowired’ and ‘@Inject’ field throw a ‘NoSuchBeanDefinitionException’ error because it can not find a bean that matches the ‘@Qualifier’.

 org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [com.sourceallies.Party] found for dependency: 
expected at least 1 bean which qualifies as autowire candidate for this dependency. 
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true),
@org.springframework.beans.factory.annotation.Qualifier(value=bad)}

Conclusions

With the exception of test 2 & 7 the configuration and outcomes were identical. When I looked under the hood I determined that the ‘@Autowired’ and ‘@Inject’ annotation behave identically. Both of these annotations use the ‘AutowiredAnnotationBeanPostProcessor’ to inject dependencies. ‘@Autowired’ and ‘@Inject’ can be used interchangeable to inject Spring beans. However the ‘@Resource’ annotation uses the ‘CommonAnnotationBeanPostProcessor’ to inject dependencies. Even though they use different post processor classes they all behave nearly identically. Below is a summary of their execution paths.

@Autowired and @Inject

  1. Matches by Type
  2. Restricts by Qualifiers
  3. Matches by Name

@Resource

  1. Matches by Name
  2. Matches by Type
  3. Restricts by Qualifiers (ignored if match is found by name)

While it could be argued that ‘@Resource’ will perform faster by name than ‘@Autowired’ and ‘@Inject’ it would be negligible. This isn’t a sufficient reason to favor one syntax over the others. I do however favor the ‘@Resource’ annotation for it’s concise notation style.

@Resource(name="person")
@Autowired
@Qualifier("person")
@Inject
@Qualifier("person")

You may argue that they can be equal concise if you use the field name to identify the bean name.

@Resource
private Party person;
@Autowired
private Party person;
@Inject
private Party person;

True enough, but what happens if you want to refactor your code? By simply renaming the field name you’re no longer referring to the same bean. I recommend the following practices when wiring beans with annotations.

Spring Annotation Style Best Practices

  1. Explicitly name your component [@Component("beanName")]
  2. Use ‘@Resource’ with the ‘name’ attribute [@Resource(name="beanName")]
  3. Avoid ‘@Qualifier’ annotations unless you want to create a list of similar beans. For example you may want to mark a set of rules with a specific ‘@Qualifier’ annotation. This approach makes it simple to inject a group of rule classes into a list that can be used for processing data.
  4. Scan specific packages for components [context:component-scan base-package="com.sourceallies.person"]. While this will result in more component-scan configurations it reduces the chance that you’ll add unnecessary components to your Spring context.

Following these guidelines will increase the readability and stability of your Spring annotation configurations.

 

from http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/

 

分享到:
评论

相关推荐

    学习Spring笔记_Annotation(注解)_Autowired_Qualifier

    除了`@Autowired`,Spring框架还提供了其他的依赖注入注解,如`@Resource`(主要用于JSR-250规范,基于名称的注入)和`@Inject`(JSR-330规范,基于类型和名称的注入)。这些注解在不同的场景下有不同的优势,开发者...

    Java-Spring各种依赖注入注解的区别.doc

    Spring提供了多种注解来实现依赖注入,包括@Autowired、@Inject和@Resource。它们各有特点,下面将详细解释它们之间的区别。 首先,@Autowired是Spring框架自身提供的注解,主要用于类型匹配的自动装配。它具有一个...

    dependency-injection-spring:Spring依赖注入的最简单示例

    没有XML的Spring Dependency Injection示例 最简单的示例Spring ...批注@ Inject,@ Resource和@Autowired之间的区别 更多演示 Java EE World示例可在以下位置找到: : 可以在这里找到Spring Wordl示例: :

    spring注解实现注入.zip

    在Spring框架中,注解注入是一种非常常用且强大的依赖注入(Dependency Injection,简称DI)方式。依赖注入是Spring的核心特性之一,它允许开发者在不直接创建对象的情况下,将依赖关系从对象代码中分离出来,提高了...

    Spring依赖注入——java项目中使用spring注解方式进行注入.rar

    在Java开发领域,Spring框架是应用最广泛的轻量级框架之一,它提供了强大的依赖注入(Dependency Injection,简称DI)功能,极大地简化了组件之间的耦合。本知识点将深入探讨Spring框架如何通过注解方式实现依赖注入...

    spring-autowire.zip

    当在某个字段或方法上添加了@Autowired,Spring容器会自动寻找合适的bean进行注入,而无需手动使用`@Resource`或`@Inject`来指定bean的名称。 在IDEA 2020中创建Spring项目并引入Spring Web依赖,我们可以创建几个...

    spring注解方式解析

    在Spring中,我们可以使用注解如`@Inject`、`@Resource`、`@Autowired`以及构造函数、setter方法、field级别的注解来实现依赖注入。例如: ```java @Component public class UserRepository { private ...

    Spring限定器demo

    此外,`@Qualifier`可以与`@Resource`、`@Inject`和`@Autowired`一起使用,但`@Qualifier`通常用于更复杂的场景,例如当`@Autowired`不能唯一确定bean时。`@Resource`注解默认是通过bean的名字来查找,所以有时可以...

    Spring面试宝典 不看后悔

    Spring的核心特性包括依赖注入(Dependency Injection, DI)、面向切面编程(Aspect Oriented Programming, AOP)以及一系列针对Web应用的集成解决方案。 #### 二、Spring IoC容器中的Bean管理 - **`@Autowired` ...

    跟我学Spring3(3.3)更多的DI知识Java开发J

    Spring框架是Java开发中的核心组件,它以依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,AOP)为主要特点,极大地简化了企业级应用的开发工作。在Spring 3.3版本中,DI机制...

    java巩固练习Spring 的bean注入方式有几种demo例子

    在类或方法上使用`@Autowired`、`@Resource`或`@Inject`注解可以实现注入。`@Autowired`基于类型匹配,`@Resource`基于名称匹配,而`@Inject`遵循JSR-330规范。例如: ```java @Component public class BeanA { ...

    spring2.5需要的jar

    Spring 2.5对依赖注入进行了优化,支持了基于注解的依赖注入,使得开发者无需编写XML配置文件,可以直接在类的字段或方法上使用`@Autowired`、`@Qualifier`等注解进行依赖注入。此外,还引入了`@Inject`注解,它是...

    bean_lifecycle.zip

    在Java开发中,Spring框架是应用最广泛的IoC(Inversion of Control)和DI(Dependency Injection)容器之一。Bean在Spring框架中扮演着核心角色,它们代表了应用程序中的对象。本篇文章将深入探讨Spring Bean的生命...

    spring3 jdbc备份资料

    此外,`@Component`、`@Service`、`@Repository`和`@Controller`等注解用于标记组件类,而`@Inject`或`@Resource`注解则用于字段或方法级别的依赖注入。 3. **Java配置**:Spring3.0引入了Java配置类,允许在Java...

    spring-framework-3.2.8.RELEASE

    它支持了更丰富的注解,如`@Autowired`、`@Qualifier`和`@Resource`,使得依赖注入更加灵活。此外,该版本还增强了对JSR-330标准的支持,引入了`@Inject`注解,与Google Guice框架兼容,进一步提升了代码的可读性...

    spring常见的一些面试题

    常用的注解有`@Autowired`、`@Inject`和`@Resource`。 ### 控制反转(IoC) 1. **概念**:控制反转是一种编程原则,指的是将对象的创建和管理控制权从应用代码中移出,由容器(比如Spring IoC容器)管理。这种方式...

    spring依赖注入

    除了上述两种基本方式,Spring还提供了基于注解的配置,例如`@Resource`、`@Inject`以及`@Qualifier`等,以提供更多的灵活性和控制。`@Resource`用于按名称注入,`@Inject`遵循JSR-330规范,与JSR-250的`@Managed...

    Spring技术内幕:深入解析Spring架构与设计原理.

    书中会详细介绍如何使用@Autowired、@Resource、@Inject等注解实现自动装配,以及XML配置方式的DI。 2. **面向切面编程(Aspect-Oriented Programming, AOP)**:Spring的AOP模块提供了一种在程序运行时,动态地将...

    spring5-di-demo:Spring 5依赖注入演示

    然后,通过@ Inject、@Autowired和@Resource等注解,可以在类内部注入所需的依赖。 1. @Autowired:Spring默认按照类型匹配,如果存在多个候选Bean,则可以通过@Qualifier指定特定的Bean。此外,@Autowired还可以...

    J2EE企业级项目开发-3期(KC007) 7.2 精解Spring之IoC原理与具体使用文档.docx

    通过@Autowired、@Resource、@Inject等注解,Spring容器会自动匹配并注入依赖。 3. **容器初始化**:Spring容器读取配置文件,创建并管理Bean实例,处理依赖注入。 4. **Bean的生命周期管理**:Spring容器负责Bean的...

Global site tag (gtag.js) - Google Analytics