Spring框架中@Autowired、@Resource、@Inject注解实现原理是什么?
摘要:你知道Spring中的@Autowired,@Resource,@Inject 这些注解的实现原理么?
使用案例
前置条件: 现在有一个 Vehicle 接口,它有两个实现类 Bus 和 Car ,现在还有一个类 VehicleService 需要注入一个 Vehicle 类型的 Bean:
public interface Vehicle {}
@Component
public class Car implements Vehicle {}
@Component
public class Bus implements Vehicle {}
使用 @Autowired 注解注入 Bean:
@Autowired 注解可以和 @Qualifier 注解一起使用,在有多个符合条件的 Bean 的情况下限制注入特定名称的 Bean:
@Component
public class VehicleService {
@Autowired
@Qualifier("car") //假设这里是想要注入Bean名称为car的这个Bean
private Vehicle vehicle;
}
使用 @Inject 注解注入 Bean:
@Inject 注解可以和 @Qualifier或者 @Named 注解一起使用,在有多个符合条件的 Bean 的情况下限制注入特定名称的 Bean:
@Component
public class VehicleService {
@Inject
@Qualifier("car") //假设这里是想要注入Bean名称为car的这个Bean
private Vehicle vehicle;
@Inject
@Named("bus") //假设这里是想要注入Bean名称为bus的这个Bean
private Vehicle anotherVehicle;
}
使用 @Resource 注解注入 Bean:
@Component
public class VehicleService {
@Resource(name = "car")
private Vehicle vehicle;
}
虽然以上三种使用方法都能够实现注入 Bean 的需求,但是它们在底层实现上有什么区别呢?
注解体系
在 Java EE 和 Spring 体系中定义了几套注解:
JSR 250:定义了 @PostConstruct,@PreDestroy,@Resource 注解,其中 @Resource 注解默认是按照名称进行注入。
JSR 330:定义了 @Inject,@Qualifier, @Named 注解,其中 @Inject 注解默认是按照类型进行注入,可以搭配 @Qualifier 或者@Named 注解实现按照名称注入。
Spring:定义了 @Autowired,@Qualifier注解,其中 @Autowired 注解默认是按照类型进行注入,可以搭配 @Qualifier 注解实现按照名称注入。
当前 JSR 250 定义的注解属于 jakarta.annotation-api,而 JSR 330 定义的注解属于 jakarta.inject-api。
实现原理
InstantiationAwareBeanPostProcessor 方法调用触发的位置:
Spring 中提供了 InstantiationAwareBeanPostProcessor 接口,它有一个 postProcessProperties() 负责实现对 Bean 的属性进行处理。
Spring 中提供了实现类 CommonAnnotationBeanPostProcessor 负责处理 @Resource 注解;提供了实现类 AutowiredAnnotationBeanPostProcessor 负责处理 @Autowired 注解和 @Inject 注解。
InstantiationAwareBeanPostProcessor的 postProcessProperties() 方法是在 AbstractAutowireCapableBeanFactory 中的 doCreateBean() 创建 Bean 的方法中触发调用的,在这个方法中的主要实现逻辑是实例化 Bean -> 填充 Bean 属性 -> 初始化 Bean。
