1. 程式人生 > 其它 >「聊一聊Spring」Spring 中 @Autowired 和 @Resource

「聊一聊Spring」Spring 中 @Autowired 和 @Resource

@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 的相關程式碼如下: