天天看點

@Autowired注解實作原理

在讨論代碼細節之前,我們再來了解下基礎知識。Spring管理可用于整個應用程式的Java對象bean。他們所在的Spring容器,被稱為應用程式上下文。這意味着我們不需要處理他們的生命周期(初始化,銷毀)。該任務由此容器來完成。另外,該上下文具有入口點,在Web應用程式中,是dispatcher servlet。容器(也就是該上下文)會在它那裡被啟動并且所有的bean都會被注入。

說的再清楚點,請看<context:annotation-config />的定義:

<xsd:element name="annotation-config">

<xsd:annotation>

<xsd:documentation><![CDATA[

Activates various annotations to be detected in bean classes: Spring's @Required and

@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),

JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's

@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may

choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's

@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>

tag for that purpose.

See javadoc for org.springframework.context.annotation.AnnotationConfigApplicationContext

for information on code-based alternatives to bootstrapping annotation-driven support.

]]></xsd:documentation>

</xsd:annotation>

</xsd:element>

可以看出 : 類内部的注解,如:@Autowired、@Value、@Required、@Resource以及EJB和WebSerivce相關的注解,是容器對Bean對象執行個體化和依賴注入時,通過容器中注冊的Bean後置處理器處理這些注解的。

是以配置了上面這個配置(<context:component-scan>假如有配置這個,那麼就可以省略<context:annotation-config />)後,将隐式地向Spring容器注冊AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor以及這4個專門用于處理注解的Bean後置處理器。

當 Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 将掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有@Autowired 注解時就找到和其比對(預設按類型比對)的 Bean,并注入到對應的地方中去。 源碼分析如下:

通過org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor可以實作依賴自動注入。通過這個類來處理@Autowired和@Value這倆Spring注解。它也可以管理JSR-303的@Inject注解(如果可用的話)。在AutowiredAnnotationBeanPostProcessor構造函數中定義要處理的注解:

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter

implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

...

/**

* Create a new AutowiredAnnotationBeanPostProcessor

* for Spring's standard {@link Autowired} annotation.

* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.

*/

@SuppressWarnings("unchecked")

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注解進行處理。

第一個,private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz)解析等待自動注入類的所有屬性。它通過分析所有字段和方法并初始化org.springframework.beans.factory.annotation.InjectionMetadata類的執行個體來實作。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {

LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();

Class<?> targetClass = clazz;

do {

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

//分析所有字段

ReflectionUtils.doWithLocalFields(targetClass, field -> {

//findAutowiredAnnotation(field)此方法後面會解釋

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, method -> {

Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);

if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {

AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);

if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {

if (Modifier.isStatic(method.getModifiers())) {

logger.warn("Autowired annotation is not supported on static methods: " + method);

if (method.getParameterCount() == 0) {

logger.warn("Autowired annotation should only be used on methods with parameters: " +

method);

PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);

currElements.add(new AutowiredMethodElement(method, required, pd));

elements.addAll(0, currElements);

targetClass = targetClass.getSuperclass();

while (targetClass != null && targetClass != Object.class);

//傳回一個InjectionMetadata初始化的對象執行個體

return new InjectionMetadata(clazz, elements);

* 'Native' processing method for direct calls with an arbitrary target instance,

* resolving all of its fields and methods which are annotated with {@code @Autowired}.

* @param bean the target instance to process

* @throws BeanCreationException if autowiring failed

public void processInjection(Object bean) throws BeanCreationException {

Class<?> clazz = bean.getClass();

InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);

metadata.inject(bean, null, null);

catch (BeanCreationException ex) {

throw ex;

catch (Throwable ex) {

throw new BeanCreationException(

"Injection of autowired dependencies failed for class [" + clazz + "]", ex);

InjectionMetadata類包含要注入的元素的清單。注入是通過Java的API Reflection (Field set(Object obj, Object value) 或Method invoke(Object obj,Object ... args)方法完成的。此過程直接在AutowiredAnnotationBeanPostProcessor的方法中調用public void processInjection(Object bean) throws BeanCreationException。它将所有可注入的bean檢索為InjectionMetadata執行個體,并調用它們的inject()方法。

public class InjectionMetadata {

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

Collection<InjectedElement> checkedElements = this.checkedElements;

Collection<InjectedElement> elementsToIterate =

(checkedElements != null ? checkedElements : this.injectedElements);

if (!elementsToIterate.isEmpty()) {

boolean debug = logger.isDebugEnabled();

for (InjectedElement element : elementsToIterate) {

if (debug) {

logger.debug("Processing injected element of bean '" + beanName + "': " + element);

//看下面靜态内部類的方法

element.inject(target, beanName, pvs);

public static abstract class InjectedElement {

protected final Member member;

protected final boolean isField;

* Either this or {@link #getResourceToInject} needs to be overridden.

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)

throws Throwable {

if (this.isField) {

Field field = (Field) this.member;

ReflectionUtils.makeAccessible(field);

field.set(target, getResourceToInject(target, requestingBeanName));

else {

if (checkPropertySkipping(pvs)) {

//具體的注入看此處咯

Method method = (Method) this.member;

ReflectionUtils.makeAccessible(method);

method.invoke(target, getResourceToInject(target, requestingBeanName));

catch (InvocationTargetException ex) {

throw ex.getTargetException();

AutowiredAnnotationBeanPostProcessor類中的另一個重要方法是private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao)。它通過分析屬于一個字段或一個方法的所有注解來查找@Autowired注解。如果未找到@Autowired注解,則傳回null,字段或方法也就視為不可注入。

@Nullable

private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {

if (ao.getAnnotations().length > 0) {

for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {

AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);

if (attributes != null) {

return attributes;

return null;

在上面的文章中,我們看到了Spring中自動注入過程。通過整篇文章可以看到,這種依賴注入是一種便捷易操作方式(可以在字段以及方法上完成),也促使我們逐漸在抛棄XML配置檔案。還增強了代碼的可讀性。