@Resource
概念
@Resource是Java EE规范的一部分,它属于Java的JSR-250规范,后来也被Spring支持。
这个注解主要用于依赖注入(DI),允许容器在运行时自动为标注的字段或方法注入所需的资源。
它允许你通过名称或者类型注入Bean。
它可以用于注入各种类型的资源,如EJB组件、数据源、JMS队列等,但最常见的是用于注入由Spring框架管理的Bean。
通俗说法
想象一下,你在经营一家餐厅,你需要确保厨师有刀具、炉子等工具来烹饪食物。
@Resource
就像是一个贴心的助手,它会在厨师(代码中的类)开始工作前,自动地将这些工具(比如数据库连接、其他服务类等)准备好并放到厨师手边(即类的成员变量中)。这样,厨师(代码)就可以直接使用这些工具而不需要自己去寻找或者创建它们,大大提高了效率。
举个例子,如果你的程序需要操作数据库,以前可能需要手动创建数据库连接对象,但现在有了 @Resource
,你只需要在需要使用数据库连接的地方声明一个变量,然后用这个注解标记它,容器(比如Spring框架)就会自动帮你找到并注入一个可用的数据库连接实例。
所属
Java EE标准,同时被Spring框架支持。
import javax.annotation.Resource;
作用
提供依赖注入的功能,可以根据名称或类型的匹配来注入Bean。默认情况下,它首先尝试按名称匹配Bean,如果找不到,则尝试按类型匹配。
用法
- 字段注入: @Resource(name="myService") private MyService myService;
- 如果不指定name属性,默认使用字段名或方法名尝试匹配: @Resource private MyService myService;
使用场景
适合于当你需要更细粒度控制依赖注入,特别是当依赖Bean的名称与注入点的字段或方法名一致,或者你需要明确指定Bean名称时。
对比 @Autowired
使用这两个注解的优缺点
@Autowired
优点:
- 类型驱动,简化配置,通常只需关注类型匹配即可。
- 支持构造器、字段、方法和参数级别的注入,使用灵活。
- 强制依赖项的存在,有助于设计更健壮的代码结构。
缺点:
- 默认情况下不支持名称匹配,当有多个相同类型的Bean时可能造成歧义。
- 隐藏了依赖关系,不如构造器注入明显,可能降低代码可读性。
- 测试时,需要模拟依赖时可能较为繁琐。
@Resource
优点:
- 支持名称匹配,提供了额外的灵活性,特别适合于解决依赖冲突或需要特定命名约定的情况。
- 由于是Java EE标准,因此具有更好的跨框架兼容性。
- 可以通过指定name属性精确控制注入的Bean。
缺点:
- 默认按名称匹配,可能导致在未明确指定名称时,依赖注入的意图不如类型驱动明确。
- 默认required属性为false,意味着如果没有匹配的Bean,该注解会被忽略,这可能引入潜在的错误或混淆。
- 不如
@Autowired
那样广泛集成于Spring框架的其他特性中,可能在一些高级功能上支持不足。
举例说明“类型驱动”和“名称匹配”
1. 类型驱动
类型驱动匹配就像是在咖啡店点咖啡,你说:“我要一杯拿铁。”
无论哪位咖啡师在吧台,只要你点的是拿铁,他们都知道怎么制作,你不在乎是哪一位咖啡师为你服务,你在乎的是得到一杯拿铁。
这里的“拿铁”就是类型,你依靠类型来获得想要的产品,而不关心具体的提供者是谁。
代码演示
想象我们有两个实现了相同接口的Service类,分别是 EmailService
和 SmsService
,而我们的 Controller
需要注入一个实现该接口的服务。
public interface MessageService {
void sendMessage(String message);
}
@Service("emailService")
public class EmailServiceImpl implements MessageService {
// 实现细节
}
@Service("smsService")
public class SmsServiceImpl implements MessageService {
// 实现细节
}
@Controller
public class MessageController {
@Autowired
private MessageService messageService; // 类型驱动注入,Spring会根据类型找到一个合适的MessageService Bean注入
}
在这个例子中,Spring会自动根据类型 MessageService
找到一个合适的Bean注入到 messageService
字段。
假设没有特别配置,默认情况下如果没有指定名字且只有一个实现类,Spring会自动注入。如果有多个实现类且没有指定名字,可能会抛出异常或需要进一步的配置来解决歧义。
2. 名称匹配
名称匹配则像是在餐厅预订座位,你说:“我想预订靠窗有风景的‘1号桌’。”
这里,“1号桌”是特定的名称,你指定了一个具体的位置,而不是说“我想要一张桌子”。餐厅会根据这个名字找到那个特定序号的、有风景观赏优势的桌子给你预留,而不是随便安排一张桌子。
代码演示
如果我们希望在 MessageController
中明确指定使用哪个实现类,可以使用 @Qualifier
注解配合 @Autowired
。
@Controller
public class MessageController {
@Autowired
@Qualifier("emailService") // 名称匹配,指定注入名为emailService的Bean
private MessageService messageService;
}
或者使用 @Resource
注解实现名称匹配,你可以直接在注解中指定Bean的名称。
@Controller
public class MessageController {
@Resource(name = "emailService") // 名称匹配,指定注入名为emailService的Bean
private MessageService messageService;
}
在这个例子中,@Resource
注解取代了 @Autowired
+ @Qualifier
的组合。
通过在 @Resource
注解中添加 name
属性并设置为 "emailService"
,我们指定了要注入的Bean的名称,实现了与之前使用 @Qualifier
相同的功能。
@Resource
注解源自Java EE规范,它允许根据名称或按类型(默认行为)进行注入,当指定了 name
属性时,它就按照名称匹配的方式工作。
测试评论~
123