「聊一聊Spring」Spring 中 @Autowired 和 @Resource
阿新 • • 發佈:2022-01-11
@Autowired 和 @Resource 的區別
- 區別一:所屬不同。
- @Autowired 是 spring-beans 模組提供的註解。
- @Resource 是 JSR 250 規範提出的註解,由 JDK 自帶。
- 區別二:裝配方式不同。兩者都可以標註在屬性或 setter 方法上。
- @Autowired 註解只能按照型別裝配依賴,如果需要按照名稱裝配還需要指定 @Qualifier 註解。
- @Resource 預設依賴 bean 的名稱為屬性名,並且可以通過其屬性 name 進行指定。預設依賴的 bean 的型別為屬性的型別,並且可以通過 type 屬性進行指定。 如果未指定依賴的 bean 的名稱並且屬性名對應的 bean 在容器中不存在時才會按照型別進行注入,否則按照名稱進行注入依賴。
- 區別三:是否強依賴不同。
- @Autowired 指定的依賴預設必須存在,可以通過 requied 屬性指定不存在。
- @Resource 指定的依賴必須存在。
@Autowired 注入分析
Spring 使用 AutowiredAnnotationBeanPostProcessor 對 @Autowired 進行處理。具體來說注入屬性的方法位於 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject,注入方法引數的方法位於 AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject,它們的處理方式基本類似。以注入屬性的流程為例進行分析,檢視屬性注入相關程式碼如下:
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { public AutowiredFieldElement(Field field, boolean required) { super(field, null); this.required = required; } // 注入屬性 @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { // 將屬性轉換為依賴描述符 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 解析依賴 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } ... 省略部分程式碼 } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } }
可以看到,Spring 對 @Autowired 標註的屬性的注入只是將屬性轉換為依賴描述符 DependencyDescriptor ,然後呼叫 BeanFactory 解析依賴的方法。轉換為依賴描述符時需要指定是否依賴是必須的,這個值在例項化 AutowiredFieldElement 時指定。AutowiredAnnotationBeanPostProcessor 例項化 AutowiredFieldElement 的相關程式碼如下: