springboot之@Autowired注解详解

日常开发中,@Autowired注解我们经常在使用,也会配合其他的注解一起(@Qualifier、@Primary、@lazy)等。
还有就是它跟@Resource的区别在哪里?一定要看到最后!!!
那么它的一个处理流程是怎样的呢?继续看,希望给大家带来对@Autowired注解使用上的一些帮助!

按照一贯的风格,首先给大家一个整体的流程图解
在这里插入图片描述

这里我挑出了8个重要的节点,入口类是AutowiredAnnotationBeanPostProcessor,关于这个类使用场景《springboot ApplicationContext之finishBeanFactoryInitialization(getBean())下
接下来我们对各个节点进行一个解释

  1. findAutowiringMetadata,这个方法主要是对类进行一个扫描,对字段或者方法存在@Autowired注解进行存储,元素分别对应AutowiredFieldElement、AutowiredMethodElement,扫描的条件,这里列出下关键代码,会忽略带static的字段或方法
//处理字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
	MergedAnnotation<?> ann = findAutowiredAnnotation(field);
	if (ann != null) {
		//如果是static跳过
		if (Modifier.isStatic(field.getModifiers())) {
			if (logger.isInfoEnabled()) {
				logger.info("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)) {
		return;
	}
	MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
	if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
		//如果是static跳过
		if (Modifier.isStatic(method.getModifiers())) {
			if (logger.isInfoEnabled()) {
				logger.info("Autowired annotation is not supported on static methods: " + method);
			}
			return;
		}
		//如果参数的个数是0 跳过
		if (method.getParameterCount() == 0) {
			if (logger.isInfoEnabled()) {
				logger.info("Autowired annotation should only be used on methods with parameters: " +
						method);
			}
		}
		boolean required = determineRequiredStatus(ann);
		PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
		currElements.add(new AutowiredMethodElement(method, required, pd));
	}
});
  1. inject,这个就是开始注入的一个动作,分别调用AutowiredFieldElement、AutowiredMethodElement 的inject方法
  2. resolveDependency,开始进入具体的处理类DefaultListableBeanFactory,这里会对一些具体的类型分别处理,按照顺序依次是:Optional、ObjectFactory || ObjectProvider、带有@lazy注解
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		//Optional 处理
		if (Optional.class == descriptor.getDependencyType()) {
			//这里会直接走第4个步骤,并把结果存储在Optional中
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			//返回的类型是包装类型DependencyObjectProvider,在实际调用中获取bean,延迟加载的另外一种处理
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			// @lazy处理,如果返回代理对象就结束流程
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			// 一般的类型,继续
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}
  1. doResolveDependency,这里是对一般类型字段或方法进行处理,分三步:处理@value注解、处理类型是Array、Collection、Map(这里实际上会调用后面5步骤,获取满足条件的类型,然后根据不同的类型进行组装)、普通类型
@Nullable
// 步骤都是一致的,先调用findAutowireCandidates获取满足条件的类型,按照返回类型进行组装进行返回
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

	Class<?> type = descriptor.getDependencyType();

	if (descriptor instanceof StreamDependencyDescriptor) {
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		Stream<Object> stream = matchingBeans.keySet().stream()
				.map(name -> descriptor.resolveCandidate(name, type, this))
				.filter(bean -> !(bean instanceof NullBean));
		if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
			stream = stream.sorted(adaptOrderComparator(matchingBeans));
		}
		return stream;
	}
	else if (type.isArray()) {
		...
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
		if (result instanceof Object[]) {
			Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
			if (comparator != null) {
				Arrays.sort((Object[]) result, comparator);
			}
		}
		return result;
	}
	else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
		...
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		Object result = converter.convertIfNecessary(matchingBeans.values(), type);
		if (result instanceof List) {
			if (((List<?>) result).size() > 1) {
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					((List<?>) result).sort(comparator);
				}
			}
		}
		return result;
	}
	else if (Map.class == type) {
		....
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		return matchingBeans;
	}
	else {
		return null;
	}
}
  1. findAutowireCandidates,按照类型查找对应的bean类型,这里只是类型、类型、类型,不是具体的对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
	// require字段的作用,如果找到,require=false,不报错
	if (isRequired(descriptor)) {
		raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
	}
	return null;
}
protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
	// 按照类型去容器中查询
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
	// 匹配spring一些已经注册的类
	for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class<?> autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	for (String candidate : candidateNames) {
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	// 如果是空的一些另外处理
	if (result.isEmpty()) {
		boolean multiple = indicatesMultipleBeans(requiredType);
		// Consider fallback matches if the first pass failed to find anything...
		DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
		for (String candidate : candidateNames) {
			//isAutowireCandidate 这个方法会处理Qualifier注解,如果带有Qualifier,就按照名字去匹配
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
					(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty() && !multiple) {
			// Consider self references as a final pass...
			// but in the case of a dependency collection, not the very same bean itself.
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}
  1. determineAutowireCandidate,这个方法只会在找到多个满足条件的时候调用,如果待选的类型包含**@Primary**注解,就使用它,否则报错,因为spring不知道你要用哪个了
  2. resolveCandidate,这个方法就是按照名称继续bean流程获取
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
		throws BeansException {

	return beanFactory.getBean(beanName);
}
  1. 反射注入属性,这个就不解释了

流程到这里就结束,当然忽略了一些非本文注重的内容例如(java的@inject注解),我想大家应该会有点对这个注解的理解提升吧!
接下来,看看具体的实例,对应的流程的步骤,都举了个例

@Service
public class TestA{
    //1
    @Autowired
    private Optional<OptionalInstance> optionalInstance;

    //2
    @Autowired
    ObjectFactory<ObjectFactoryInstance> objectFactoryInstance;

    //3
    @Autowired
    ObjectProvider<ObjectProviderTest.ObjectProviderInstance> objectProviderInstances;

    //4
    @Autowired
    @Lazy
    private LazyTest lazyTest;

    //5方法注入,对@value的处理
    @Autowired
    private void valueTest(@Value("${spring.application.name}")String name){

    }

    @Autowired
    private TestB testB;

    private TestC testC;

	//方法注入
    @Autowired
    public void setP(TestC testC){
        this.testC =testC;
    }
	// TestD是个接口,多个类实现
    @Autowired
    private List<TestD> testDS;

	// TestE是个接口,多个类实现
    @Autowired
    @Qualifier(value = "testE1") 会注入名称为testE1的类,没有这个注解就报错拉。。。
    private TestE testE;

	// TestE是个接口,多个类实现,这样应该是会报错的但是我在其中的一个类上加了@Primary注解
    @Autowired
    private TestF testF;

    public void sayObjectFactory(){
        System.out.println(this.objectFactoryInstance.getObject());
        System.out.println(optionalInstance.isPresent());
        System.out.println(lazyTest);
    }

    public void sayObjectProvider(){
        System.out.println(this.objectProviderInstances.getIfUnique());
        System.out.println(objectProviderInstances.getIfAvailable());
        System.out.println(objectProviderInstances.getObject());
    }
}

在对代码中的ObjectFactory、ObjectProvider进行下说明吧,它的重要类似@lazy,在使用的时候再进行bean的获取,ObjectFactory还记得它吗?我们在循环依赖中,放入二级缓存的东西《springboot ApplicationContext之finishBeanFactoryInitialization(getBean())上》,ObjectProvider是它的之类扩展了一些方法getIfUnique、getIfAvailable、stream相关等,主要扩展的是,默认require =false,也就是说,如果不存在在启动的时候不会报错,使用的时候会报错
在这里插入图片描述

	private class DependencyObjectProvider implements BeanObjectProvider<Object> {

		private final DependencyDescriptor descriptor;

		private final boolean optional;

		@Nullable
		private final String beanName;

		public DependencyObjectProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
			this.descriptor = new NestedDependencyDescriptor(descriptor);
			this.optional = (this.descriptor.getDependencyType() == Optional.class);
			this.beanName = beanName;
		}

		@Override
		public Object getObject() throws BeansException {
			if (this.optional) {
				return createOptionalDependency(this.descriptor, this.beanName);
			}
			else {
				Object result = doResolveDependency(this.descriptor, this.beanName, null, null);
				if (result == null) {
					throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
				}
				return result;
			}
		}

		@Override
		public Object getObject(final Object... args) throws BeansException {
			if (this.optional) {
				return createOptionalDependency(this.descriptor, this.beanName, args);
			}
			else {
				DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
					@Override
					public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
						return beanFactory.getBean(beanName, args);
					}
				};
				Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
				if (result == null) {
					throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
				}
				return result;
			}
		}

		@Override
		@Nullable
		public Object getIfAvailable() throws BeansException {
			if (this.optional) {
				return createOptionalDependency(this.descriptor, this.beanName);
			}
			else {
				DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
					// 可以允许不存在
					@Override
					public boolean isRequired() {
						return false;
					}
				};
				return doResolveDependency(descriptorToUse, this.beanName, null, null);
			}
		}

		@Override
		@Nullable
		public Object getIfUnique() throws BeansException {
			DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
				// 可以允许不存在
				@Override
				public boolean isRequired() {
					return false;
				}
				@Override
				@Nullable
				public Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) {
					return null;
				}
			};
			if (this.optional) {
				return createOptionalDependency(descriptorToUse, this.beanName);
			}
			else {
				return doResolveDependency(descriptorToUse, this.beanName, null, null);
			}
		}

		@Nullable
		protected Object getValue() throws BeansException {
			if (this.optional) {
				return createOptionalDependency(this.descriptor, this.beanName);
			}
			else {
				return doResolveDependency(this.descriptor, this.beanName, null, null);
			}
		}

		@Override
		public Stream<Object> stream() {
			return resolveStream(false);
		}

		@Override
		public Stream<Object> orderedStream() {
			return resolveStream(true);
		}

		@SuppressWarnings("unchecked")
		private Stream<Object> resolveStream(boolean ordered) {
			DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);
			Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
			return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));
		}
	}

接下来我们来聊聊@Autowired、@resource的区别在哪里,看到流程图中的那个箭头了吗!!!在这里插入图片描述
就是inject方法再调用具体的类型的inject方法是多了个判断,@resource注解的作用类是CommonAnnotationBeanPostProcessor,她调用findResourceMetadata返回的对象是ResourceElement,我们看下该类的inject方法(实际调用的父类InjectionMetadata.InjectedElement)

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)) {
			return;
		}
		try {
			Method method = (Method) this.member;
			ReflectionUtils.makeAccessible(method);
			method.invoke(target, getResourceToInject(target, requestingBeanName));
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}
}

调用都是getResourceToInject,这个方法ResourceElement进行重写,

@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
	// @lazy注解分开处理
	return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
			getResource(this, requestingBeanName));
}

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
	throws NoSuchBeanDefinitionException {
//忽略了其它一些
....
return autowireResource(this.resourceFactory, element, requestingBeanName);
}

autowireResource就是重要的区别方法了,仔细、仔细看下方法会判断factory.containsBean(name)是否存在,如果不存在就转交成@Autowired处理,如果存在直接按照名称获取(这个时候就不会存在返回多bean了,但是如果名称对应的类型跟定义的类型不一致就会报错)

protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
			throws NoSuchBeanDefinitionException {

		Object resource;
		Set<String> autowiredBeanNames;
		String name = element.name;

		if (factory instanceof AutowireCapableBeanFactory) {
			AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
			DependencyDescriptor descriptor = element.getDependencyDescriptor();
			// 区别在这里。。。。,会判断factory.containsBean(name)是否存在,如果不存在就转交成@Autowired处理
			if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
				autowiredBeanNames = new LinkedHashSet<>();
				resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
				if (resource == null) {
					throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
				}
			}
			//已经存在的,直接按照名称获取
			else {
				resource = beanFactory.resolveBeanByName(name, descriptor);
				autowiredBeanNames = Collections.singleton(name);
			}
		}
		else {
			resource = factory.getBean(name, element.lookupType);
			autowiredBeanNames = Collections.singleton(name);
		}

		if (factory instanceof ConfigurableBeanFactory) {
			ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
			for (String autowiredBeanName : autowiredBeanNames) {
				if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
					beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
				}
			}
		}

		return resource;
	}

个人总结下两者的区别:

  • @Resource,优先按照名称注入,存在,进入bean的获取流程;不存在,回滚到@Autowired
  • @Autowired,按照类型注入
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值