@autowire、@resource原理


@autowire、@resource、@value是我們項目開發中最常用的注解。

對於初學者來說

@value注入配置屬性

@autowire根據類型注入

@resource根據名字注入

其實這種理解不是很透徹

今天我們來探索下@autowire的原理。

一、准備測試代碼

一個接口類有多個實現類

public interface UserService {

}

--

@Service("userService1")
public class UserService1Impl implements UserService {

}

--
@Service("userService2")
public class UserService2Impl implements UserService {

}

需要注入的類

public interface UniqueService {

    void a();

}

--
@Service
public class UniqueServiceImpl implements UniqueService {

    @Autowired
    private UserService userService1;

    @Value("${test.a}")
    private String a;

    @Override
    public void a() {
        System.out.println(a);
    }
}

xml配置

<context:property-placeholder location="classpath:application.properties"/>
<context:component-scan base-package="com.csy.discuss.core.autowire"/>

二、源碼分析

1.AutowiredAnnotationBeanPostProcessor初始化

注:這一點其實大部分知識點都與Spring容器的初始化和Spring命名空間有關。

當spring解析<context:component-scan>標簽的時候找到對應的ComponentScanBeanDefinitionParser命名空間解析器

//ComponentScanBeanDefinitionParser#registerComponents

protected void registerComponents(
			XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

	...

	// Register annotation config processors, if necessary.
	boolean annotationConfig = true;
	if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
		annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
	}
	if (annotationConfig) {
		Set<BeanDefinitionHolder> processorDefinitions =
				AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
		for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
			compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
		}
	}

	readerContext.fireComponentRegistered(compositeDef);
}

因為<context:component-scan>標簽annotation-config屬性默認為true。所以
調用AnnotationConfigUtils.registerAnnotationConfigProcessors。
里面手動注冊了AutowiredAnnotationBeanPostProcessor這個bean。

Spring創建AutowiredAnnotationBeanPostProcessor這個bean的時候調用其構造方法

public AutowiredAnnotationBeanPostProcessor() {
	this.autowiredAnnotationTypes.add(Autowired.class);
	this.autowiredAnnotationTypes.add(Value.class);
	try {
		this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
				ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
		logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

我們可以看到。它初始化了Autowired、Value、Inject三個注解。也就是說這三個注解都是由AutowiredAnnotationBeanPostProcessor來實現的。

2.組裝InjectionMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
	Class<?> targetClass = clazz;

	do {
		final LinkedList<InjectionMetadata.InjectedElement> currElements =
				new LinkedList<InjectionMetadata.InjectedElement>();

		ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
			@Override
			public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			}
		});

		ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
				...
			}
		});

		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);

	return new InjectionMetadata(clazz, elements);
}

我們可以看兩個主方法:doWithLocalFields和doWithLocalMethods。顧名思義,處理屬性和方法上的@autowire類注解。也就是說@autowire不僅可以打在類的屬性上,還能打在類的方法上。打在方法上我們不做分析,因為基本不用。
然后遍歷這個類上所有的屬性。篩選出帶有@Autowire或@Value或@Inject的屬性。最終組裝成InjectionMetadata。

3.注入

doCreateBean -> populateBean -> InstantiationAwareBeanPostProcessor#postProcessPropertyValues

AutowiredAnnotationBeanPostProcessor就是繼承InstantiationAwareBeanPostProcessor。

public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
	   // AutowiredFieldElement.inject
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

首先,就是拿到我們第二步組裝好的InjectionMetadata,然后遍歷里面的InjectedElement。即遍歷這個bean所有帶有@Autowire或@Value或@Inject的屬性。

AutowiredAnnotationBeanPostProcessor有兩個私有內部類AutowiredFieldElement和AutowiredMethodElement,都繼承InjectionMetadata的內部類InjectedElement。顯而易見,我們要跟蹤的是AutowiredFieldElement。

//DefaultListableBeanFactory

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
			Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		
		//@Value注解走這里
		if (value != null) {
			if (value instanceof String) {
				String strVal = resolveEmbeddedValue((String) value);
				BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			return (descriptor.getField() != null ?
					converter.convertIfNecessary(value, type, descriptor.getField()) :
					converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
		}
      
        //@Autowire注解走這里
		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
			return multipleBeans;
		}

		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(type, matchingBeans);
				}
				else {
					// In case of an optional Collection/Map, silently ignore a non-unique case:
					// possibly it was meant to be an empty collection of multiple regular beans
					// (before 4.3 in particular when we didn't even look for collection beans).
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		return (instanceCandidate instanceof Class ?
				descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
	}
	finally {
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

3.1@Value注解鏈路

這個不多分析了。主要通過PropertySourcesPlaceholderConfigurer去解析

3.2@Autowire注解鏈路

以測試代碼注入的UserService userService1為例。

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

candidates老朋友了,候選者的意思。

從bean工廠中撈出UserService類型的bean。以這個bean的名字為key。若bean已經創建完成,那么以這個bean的實例為value。否則以這個bean的類型為value;

對於測試代碼的例子來說。有兩個候選者。分別是userService1和userService2

如果matchingBeans有多個,那就根據對應屬性的名字進行匹配。

return (instanceCandidate instanceof Class ?
					descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);

如果是class類型那么調用beanFactory.getBean進行bean的創建,拿到這個bean的實例。

AutowiredFieldElement#inject的最后幾句代碼

if (value != null) {
	ReflectionUtils.makeAccessible(field);
	field.set(bean, value);
}

通過反射將屬性設置進去。

四、順便提一下@Resource注解

由CommonAnnotationBeanPostProcessor實現

看beanDefinitionMap里是否有這個屬性名稱的bean。沒有的話根據類型走和@autowire一樣的doResolveDependency方法。有這個屬性名稱的bean,直接創建這個bean。

總結

1.@autowire、@resource、@value是通過調用AutowiredAnnotationBeanPostProcessor這個BeanPostProsess的postProcessPropertyValues方法進行注入的

2.@Autowire不僅可以作用在bean的屬性上,還能作用在bean的方法上。

3.@Autowire通過屬性的類型進行注入。若這個類型有多種(一個接口類有多個實現類),降級為根據名字來注入

4.@Resource通過屬性的名字去容器里找bean的定義。有的話直接創建bean進行注入。沒有的話降級為根據類型進行注入


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM