微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

@Autowired注解源码解析

我们先来写一个简单的demo方便debug调试。

public class QualifierDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
        applicationContext.register(QualifierDemo.class);
        applicationContext.refresh();

        applicationContext.close();
    }

    @Autowired
    private User user;


    @Bean
    public User user(){
        return createuser("user1");
    }

    private static User createuser(String name){
        User user=new User();
        user.setName(name);
        return user;
    }
}

首先我们来关注这个方法AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDeFinition,这个类实现了BeanPostProcessor的子接口,所以bean在实例化的时候会执行到这个方法

    @Override
	public void postProcessMergedBeanDeFinition(RootBeanDeFinition beanDeFinition,Class<?> beanType,String beanName) {
	    //获取加了@Autowired的元信息数据
		InjectionMetadata Metadata = findAutowiringMetadata(beanName,beanType,null);
		//将beanDeFinition里Autowired相关信息添加到checkedElements里面,后面会用到。
		Metadata.checkConfigMembers(beanDeFinition);
	}

我们可以看到上面这个方法到入参里有个beanDeFinition,这个beanDeFinition正是QualifierDemo的实例,然后通过findAutowiringMetadata方法会去找关于Autowired的元信息。
这个方法执行完后,会执行AutowiredAnnotationBeanPostProcessor#postProcessproperties方法

@Override
	public PropertyValues postProcessproperties(PropertyValues pvs,Object bean,String beanName) {
	    //获取一些元信息
		InjectionMetadata Metadata = findAutowiringMetadata(beanName,bean.getClass(),pvs);
		try {
		    //关键的方法
			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;
	}

这里面关键的方法就是inject方法,他的代码如下:

public void inject(Object target,@Nullable String beanName,@Nullable PropertyValues pvs) throws Throwable {
        //取之前存入的checkedElements
		Collection<InjectedElement> checkedElements = this.checkedElements;
		//没有的话就取injectedElements,也是之前存入的
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
		    //遍历@Autowired注解标记了的元信息数据集合,我们的示例中只有一个@Autowired  User
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				//element正是我们示例代码里的User的一些描述
				element.inject(target,pvs);
			}
		}
	}

element的结构图如下:


可以看出,这个类型就是我们的User。接着往下看element#inject方法

        @Override
		protected void inject(Object bean,@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 {
				    //根据元信息描述去进行bean查找
					value = beanfactory.resolveDependency(desc,autowiredBeanNames,typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null,new InjectionPoint(field),ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName,autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanfactory.containsBean(autowiredBeanName) &&
										beanfactory.isTypeMatch(autowiredBeanName,field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc,autowiredBeanName,field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			//将查找到的bean通过反射set到对象中及示例中的 @Autowired private User user;
			if (value != null) {
			    //反射操作给private属性需要的操作。
				ReflectionUtils.makeAccessible(field);
				field.set(bean,value);
			}
		}
	}

通过反射将查找到到bean注入到@Autowired注解到变量上。

另外,源码中分析要经过的两个方法postProcessMergedBeanDeFinition和postProcessproperties,他们是因为实现了spring的接口,所以会被调用到。下面我们写个例子证实它。

@Configuration
public class BeanPostConfig implements MergedBeanDeFinitionPostProcessor,InstantiationAwareBeanPostProcessor {
    @Override
    public void postProcessMergedBeanDeFinition(RootBeanDeFinition beanDeFinition,String beanName) {
        System.out.println("postProcessMergedBeanDeFinition:"+beanName);
    }


    @Override
    public PropertyValues postProcessproperties(PropertyValues pvs,String beanName) {
        System.out.println("postProcessproperties:"+beanName);
        return pvs;
    }
}

打印结果如下:

postProcessMergedBeanDeFinition:qualifierDemo
postProcessMergedBeanDeFinition:user
postProcessproperties:user
postProcessproperties:qualifierDemo

事实证明实现了接口后,两个方法都被执行了,并且会将postProcessMergedBeanDeFinition方法执行完之后才开始调用postProcessproperties方法

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐