千字详解@Autowired和@Resource (附代码示例)

时间:2025-02-21 11:53:38

在Spring框架中,@Autowired@Resource都是用来进行依赖注入的注解

@Autowired和@Resource所属的包不同,这反映了它们不同的来源和设计理念

@Autowired:这个注解是由Spring框架提供的,属于包。它是Spring框架的一部分,用于实现依赖注入的功能。Spring框架从2.5版本开始对依赖注入的方式进行了改进,使得@Autowired成为了一个更加便捷和强大的注解。

@Resource:与@Autowired不同,@Resource注解来源于Java的JSR-250规范提案,属于包。这意味着@Resource是Java平台的一部分,而不是特定于Spring框架的。它需要JDK1.6及以上版本才能使用。由于JSR-250是一个通用的注解,因此它可以在不同的Java EE容器中使用,而不仅仅是Spring。

依赖查找顺序不同

当使用@Autowired注解进行依赖注入时,Spring会按照以下顺序进行匹配:

按类型匹配:首先根据被注入属性的类型查找容器中是否存在对应的bean。如果存在多个相同类型的bean,则继续下一步的匹配。

按名称匹配:如果存在多个相同类型的bean,Spring会根据被注入属性的名称与容器中的bean名称进行匹配。如果找到与名称匹配的bean,则将其注入到目标对象中。

抛出异常:如果没有找到匹配的bean,则会抛出NoSuchBeanDefinitionException异常。

举例说明:

假设我们有一个接口UserService和两个实现类UserServiceImplAUserServiceImplB,它们都实现了UserService接口。同时,在Spring容器中定义了两个bean,分别名为userServiceAuserServiceB

public interface UserService {
    void doSomething();
}

public class UserServiceImplA implements UserService {
    @Override
    public void doSomething() {
        ("UserServiceImplA is doing something");
    }
}

public class UserServiceImplB implements UserService {
    @Override
    public void doSomething() {
        ("UserServiceImplB is doing something");
    }
}

 在Spring配置文件中定义了这两个bean:

<bean  class="" />
<bean  class="" />

现在我们有一个类UserController,其中有一个属性需要注入UserService

public class UserController {
    @Autowired
    private UserService userService;

    public void execute() {
        ();
    }
}

在这种情况下,Spring会先按类型匹配,发现有两个相同类型的bean(UserServiceImplAUserServiceImplB),然后根据名称进行匹配。由于UserController中没有指定具体的bean名称,所以Spring会选择其中一个bean进行注入。具体选择哪个bean取决于容器中bean的定义顺序。

@Qualifier 注解用于指定需要注入的 bean 的名称。当有多个相同类型的 bean 时,可以使用 @Qualifier 来指定具体需要注入的 bean。

@Resource注解则是先根据名称进行匹配,如果未找到与名称匹配的bean,再按类型进行查找。

如果我们在UserController中使用@Resource注解进行依赖注入:

public class UserController {
    @Resource(name = "userServiceA")
    private UserService userService;

    public void execute() {
        ();
    }
}

在这种情况下,Spring会先根据名称进行匹配,找到名为userServiceA的bean,并将其注入到UserController中。如果找不到与名称匹配的bean,才会按类型进行匹配。

注入方式不同

@Autowired支持构造方法注入、属性注入和Setter注入,而@Resource仅支持属性注入和Setter注入。

构造方法注入@Autowired可以通过在类的构造方法上添加注解来实现依赖注入。这种方式可以在对象创建时就完成依赖的注入,使得对象在创建后即可使用,而不需要等待其他依赖注入完成。

public class MyClass {
    private MyDependency myDependency;

    @Autowired
    public MyClass(MyDependency myDependency) {
         = myDependency;
    }
}

属性注入@Autowired@Resource都支持通过在类的属性上添加注解来实现依赖注入。这种方式简单直接,适用于依赖关系较为明确的情况。

@Autowired示例代码

public class MyClass {
    @Autowired
    private MyDependency myDependency;
}

@Resource示例代码:

public class MyClass {
    @Resource
    private MyDependency myDependency;
}

Setter注入@Autowired@Resource也都支持通过在类的setter方法上添加注解来实现依赖注入。这种方式符合JavaBean的规范,适用于需要在依赖注入前后进行一些处理的情况。

public class MyClass {
    private MyDependency myDependency;

    @Autowired
    public void setMyDependency(MyDependency myDependency) {
         = myDependency;
    }
}

 @Resource示例代码:

public class MyClass {
    private MyDependency myDependency;

    @Resource
    public void setMyDependency(MyDependency myDependency) {
         = myDependency;
    }
}

参数支持不同

@Autowired@Resource注解在参数支持方面存在一些差异

@Autowired@Autowired注解来自Spring框架,它支持设置一个参数,即要注入的依赖。这意味着在使用@Autowired时,通常不需要指定额外的参数,因为Spring会自动根据类型进行匹配,如果存在多个相同类型的bean,则会根据名称进行查找。

Resource@Resource注解来自于JSR-250规范,它支持设置七个参数。这些参数为@Resource提供了更多的灵活性,允许开发者指定更详细的依赖注入规则。例如,可以通过参数指定具体的名称、类型、甚至是注入的方式(如通过名称或类型)。

name参数:用于指定要注入的bean的名称。

public class MyClass {
    @Resource(name = "myDependency")
    private MyDependency myDependency;
}

type参数:用于指定要注入的bean的类型。

public class MyClass {
    @Resource(type = )
    private MyDependency myDependency;
}

mappedName参数:用于指定要注入的bean在JNDI中的名称。

authenticationType参数:用于指定身份验证类型

shareable参数:用于指定是否共享资源。

description参数:用于提供对资源的简短描述。

lookup参数:用于指定自定义的查找逻辑。

作用位置不同

@Autowired:可以是类、属性、构造方法、Setter方法和配置方法

@Resource   属性和方法

默认设计模式不同

Autowired 

默认为单例(Singleton)。这意味着在使用@Autowired进行依赖注入时,Spring容器会创建一个共享的bean实例,并将其注入到需要的地方。如果多个地方都使用了同一个bean,那么它们都将引用同一个实例。

Resource

默认为原型(Prototype)。这意味着在使用@Resource进行依赖注入时,每次请求都会创建一个新的bean实例,并将其注入到需要的地方。这样可以避免多个地方共享同一个实例的问题。

虽然@Autowired@Resource的默认值不同,但开发者可以通过设置参数来改变它们的默认设计模式。例如,可以使用@Scope注解来指定@Autowired@Resource的设计模式。