注解 @Autowired 和 @Resource
文章目录
- @Autowired 和 @Resource 的区别
- 来源和规范
- 装配方式
- 支持的注入对象
- 支持的参数
- 可选性
- 特定实现类
- 使用 @Autowired 报错,而 @Resource 不会的情况
- 存在多个匹配的 Bean。
- PersonRepository Bean 是否正确配置:
- 包扫描是否包含 PersonRepository:
- 其他配置问题:
@Autowired 和 @Resource 的区别
来源和规范
- @Autowired 是 Spring 框架提供的注解
- @Resource 是 Java EE 规范提供的注解。在 Spring 中也可以使用,但它并不是 Spring 框架特有的注解,是Java定义的注解(JDK自带),它来自于JSR-250(Java 250 规范提案)。
装配方式
- @Autowired注解是按照类型(byType)装配依赖对象。@Autowired 可以用在字段、构造函数、Setter 方法上,通过类型匹配进行自动装配。如果有多个匹配类型的 Bean,可以结合 @Qualifier 注解使用,或者通过 @Autowired(required = false) 配置为非必须的注入。
- @Resource注解默认按照名称(byName)装配依赖对象。@Resource注解包含name和type两个属性,通过这两个属性,可以分别按照bean的名称和类型进行装配。如果没有指定name属性,那么默认会使用字段的名字进行名称匹配。同时,如果指定了name和type属性,Spring会从上下文中找到唯一匹配的bean进行装配。
支持的注入对象
- @Autowired 主要用于注入 Spring 管理的 Bean,它是 Spring 框架的一部分。
- @Resource 是 Java EE 规范的一部分,可以用于注入任何 Java 对象,不仅仅是 Spring 管理的 Bean。
支持的参数
-
@Autowired 主要有两个主要的参数:
- required (boolean):默认值为 true,表示要求找到匹配的 Bean 进行注入。
如果设置为 false,表示允许没有匹配的 Bean,即允许注入为 null。 - qualifier (String):用于指定要注入的 Bean 的限定符(qualifier)。在一个容器中有多个相同类型的 Bean 时,可以使用 @Qualifier 注解进一步指定要注入的 Bean。示例:
@Autowired @Qualifier("myBean")
- required (boolean):默认值为 true,表示要求找到匹配的 Bean 进行注入。
-
@Resource 主要有两个参数:
- name (String):用于指定要注入的 Bean 的名称。如果不指定,则默认按照属性名进行匹配。示例:
@Resource(name = "myBean")
- type (Class):用于指定要注入的 Bean 的类型。如果不指定,则按照属性的类型进行匹配。示例:
@Resource(type = MyBean.class)
- name (String):用于指定要注入的 Bean 的名称。如果不指定,则默认按照属性名进行匹配。示例:
需要注意的是,@Resource 的 type 参数在 JDK 9 之后被废弃。因为 JDK 9 开始,@Autowired 已经变得更加灵活,可以替代大多数 @Resource 的用例。
可选性
- @Autowired 是非常灵活的,但它在注入时必须能够找到匹配的 Bean,否则会抛出异常,除非使用 @Autowired(required = false) 设置为非必须的。
- @Resource 可以设置 name 属性指定要注入的 Bean 的名称,但如果找不到匹配的 Bean,它会尝试按照类型进行注入。
特定实现类
- @Autowired 是 Spring 特有的注解,因此在使用 @Autowired 时,你的代码与 Spring 框架耦合。
- @Resource 是 Java EE 规范的一部分,可以在其他 Java EE 容器中使用。
在实际使用中,你可以根据具体的需求和场景选择使用 @Autowired 还是 @Resource。通常来说,@Autowired 更灵活,而 @Resource 更符合 Java EE 规范,可以提高代码的可移植性。
使用 @Autowired 报错,而 @Resource 不会的情况
如果使用 @Autowired 报错,可能是因为 Spring 框架没有找到可注入的 PersonRepository Bean。在这种情况下,可以尝试使用 @Resource 注解进行注入,或者检查以下几个可能的原因:
存在多个匹配的 Bean。
假设我们有以下代码:
@Service
class ServiceA {
@Autowired
private Dependency depA;
}
@Service
class ServiceB {
@Autowired
private Dependency depB;
}
@Service
class Dependency {}
@Service
class DependencyImpl extends Dependency {}
在这个例子中,ServiceA 和 ServiceB 都期望获得一个 Dependency 类型的依赖项。由于有两种类型的 Dependency Bean,Spring 不知道要使用哪一种,所以它将抛出异常。
如果你使用 @Resource 注解并提供具体的名称,Spring 就可以根据名称区分这两个 Bean:
@Service
class ServiceA {
@Resource(name="depA")
private Dependency depA;
}
@Service
class ServiceB {
@Resource(name="depB")
private Dependency depB;
}
@Service("depA")
class Dependency {}
@Service("depB")
class DependencyImpl extends Dependency {}
但如果没有显式地命名 Bean,则需要使用 @Qualifier 注解:
@Service
class ServiceA {
@Autowired
@Qualifier("depA")
private Dependency depA;
}
@Service
class ServiceB {
@Autowired
@Qualifier("depB")
private Dependency depB;
}
@Service("depA")
class Dependency {}
@Service("depB")
class DependencyImpl extends Dependency {}
请注意,即使你使用 @Resource 注解,如果不指定 name,它也会抛出异常。所以,如果你没有使用 @Qualifier 注解明确指出 Bean,@Autowired 也会抛出异常。
PersonRepository Bean 是否正确配置:
确保 PersonRepository 被正确配置为一个 Spring Bean。你可以在 PersonRepository 类上添加 @Repository 注解,以确保 Spring 能够扫描到并正确配置该 Bean。
@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {
}
包扫描是否包含 PersonRepository:
确保 PersonRepository 所在的包在 Spring 的包扫描范围内。你可以在主程序入口类上添加 @SpringBootApplication 注解,这样 Spring 将会扫描该类所在的包以及子包。
@SpringBootApplication
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
其他配置问题:
检查是否有其他与 Bean 配置相关的问题,比如数据库连接等。如果上述方法都不起作用,你可以尝试手动创建 PersonRepository Bean。在你的配置类中添加如下代码:
@Configuration
public class AppConfig {
@Bean
public PersonRepository personRepository() {
return new PersonRepositoryImpl(); // 请根据你的实际情况创建具体的 PersonRepository 实现类
}
}
上述代码中的 PersonRepositoryImpl 应该是 PersonRepository 接口的一个实现类。这样,在 testController 中使用 @Autowired 注解就应该正常了。