@Resource,@Autowired,@Value源码分析-浅谈Spring属性填充

在spring属性填充这里,会经常有面试官问你,常用注入方式有哪些,这些注解注入是by_type还是by_name还是什么?
其实这句话就不够严谨!如下:

使用@Bean 会有一个autowire属性 默认NO
在这里插入图片描述

属性填充时,@Autowire之前 会执行以下代码,mbd.getResolvedAutowireMode()方法 查询该RootBeanDefinition中autowire的属性,autowireByName和autowireByType两个方法都是注入点注入数据,但是很重要一点, 执行autowire声明好的注入方式选择方法.下次再面试,就可以反问面试官,autowire属性是什么?
在这里插入图片描述

  1. 重中之重后置处理器方法postProcessProperties, 有两个重要的postProcessor(AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor), 前者处理Spring的注入注解 @Autowired @Value 后者主要处理Java注入注解@Resource @WebServiceRef @EJB
    在这里插入图片描述

  2. CommonAnnotationBeanPostProcessor先看这个后置处理器 @Resource处理过程
    2.1 查找符合该处理器的bean的注解以及注入点

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    
    
	InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
	try {
    
    
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
    
    
		throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
	}
	return pvs;
}

// 2.1.1 查找该bean的注解及注入点信息
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
    
    
	// Map<String, InjectionMetadata> injectionMetadataCache beanName为String value为注入点元信息
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	
	InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
	if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    
    
		synchronized (this.injectionMetadataCache) {
    
    
			metadata = this.injectionMetadataCache.get(cacheKey);
			// 2.1.2 多说一句: 经典的Double check 多线程运行时候 容易出现第一个if 进来后 线程2等待锁 所以第二层拦掉
			if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    
    
				if (metadata != null) {
    
    
					metadata.clear(pvs);
				}
				// 2.1.3 构建resource元信息
				metadata = buildResourceMetadata(clazz);
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    
    
		// Resource WebServiceRefClass EjbClass是否有这三个注解
		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
    
    
			return InjectionMetadata.EMPTY;
		}

		// 2.1.4 注入点封装类 element
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

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

			// 2.1.5 不支持static修饰注入 这就能理解为什么static 类对象 注入不成功
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
    
    
				if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
    
    
					if (Modifier.isStatic(field.getModifiers())) {
    
    
						throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
					}
					currElements.add(new WebServiceRefElement(field, field, null));
				}
				else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
    
    
					if (Modifier.isStatic(field.getModifiers())) {
    
    
						throw new IllegalStateException("@EJB annotation is not supported on static fields");
					}
					currElements.add(new EjbRefElement(field, field, null));
				}
				else if (field.isAnnotationPresent(Resource.class)) {
    
    
					if (Modifier.isStatic(field.getModifiers())) {
    
    
						throw new IllegalStateException("@Resource annotation is not supported on static fields");
					}
					if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
    
    
						currElements.add(new ResourceElement(field, field, null));
					}
				}
			});
			// 2.1.6 static方法也不支持 setXxx(Object obj) 只能是一个参数 !=1会抛出requires a single-arg method异常
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    
    
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    
    
					return;
				}
				if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    
    
					if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
    
    
						if (Modifier.isStatic(method.getModifiers())) {
    
    
							throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
						}
						if (method.getParameterCount() != 1) {
    
    
							throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
						}
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
					}
					else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
    
    
						if (Modifier.isStatic(method.getModifiers())) {
    
    
							throw new IllegalStateException("@EJB annotation is not supported on static methods");
						}
						if (method.getParameterCount() != 1) {
    
    
							throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
						}
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new EjbRefElement(method, bridgedMethod, pd));
					}
					else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
    
    
						if (Modifier.isStatic(method.getModifiers())) {
    
    
							throw new IllegalStateException("@Resource annotation is not supported on static methods");
						}
						Class<?>[] paramTypes = method.getParameterTypes();
						if (paramTypes.length != 1) {
    
    
							throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
						}
						if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
    
    
							PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
							currElements.add(new ResourceElement(method, bridgedMethod, pd));
						}
					}
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
		// 2.1.7 返回element
		return InjectionMetadata.forElements(elements, clazz);
	}

2.2 注入代码

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
				throws Throwable {
    
    
	// 字段注入
	if (this.isField) {
    
    
		Field field = (Field) this.member;
		// 这个反射功能很强大 学习了sync lock 都知道底层是park与unpark park unpark的类不允许使用 但是通过这个方法......
		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();
		}
	}
}

// 判断是否懒加载 是:绑定一个代理 使用时候赋值 否:赋值
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
    
    
	return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
			getResource(this, requestingBeanName));
}

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
			throws NoSuchBeanDefinitionException {
    
    
// jndiFactory特殊的bean工厂 jndi百度一下 有时间了解一下: https://blog.csdn.net/u010430304/article/details/54601302
if (StringUtils.hasLength(element.mappedName)) {
    
    
	return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
if (this.alwaysUseJndiLookup) {
    
    
	return this.jndiFactory.getBean(element.name, element.lookupType);
}
if (this.resourceFactory == null) {
    
    
	throw new NoSuchBeanDefinitionException(element.lookupType,
			"No resource factory configured - specify the 'resourceFactory' property");
}
// 开始注入
return autowireResource(this.resourceFactory, element, requestingBeanName);
}

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

	Object resource;
	Set<String> autowiredBeanNames;
	// @Resource(name = "giao") UserService uservice 这列element.name就是name的属性值 giao
	String name = element.name;

	if (factory instanceof AutowireCapableBeanFactory) {
    
    
		AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
		DependencyDescriptor descriptor = element.getDependencyDescriptor();
		// element.isDefaultName=true 说明@Resource name属性值为空
		if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
    
    
			autowiredBeanNames = new LinkedHashSet<>();
			// 先 byType --> 后 byName @Autowired着重看 
			resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
			if (resource == null) {
    
    
				throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
			}
		}
		// 如果可以直接通过@resouce的name属性值 通过name和type找出来 找到factoty里这个bean
		else {
    
    
			resource = beanFactory.resolveBeanByName(name, descriptor);
			autowiredBeanNames = Collections.singleton(name);
		}
	}
	else {
    
    
		resource = factory.getBean(name, element.lookupType);
		autowiredBeanNames = Collections.singleton(name);
	}
	// 记录beanName依赖
	if (factory instanceof ConfigurableBeanFactory) {
    
    
		ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
		for (String autowiredBeanName : autowiredBeanNames) {
    
    
			if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
    
    
				beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
			}
		}
	}

	return resource;
}

2.3 总结一下@Resource
2.3.1 如果@Resource注解中指定了name属性,那么则只会根据name属性的值去找bean,如果找不到则报错
2.3.2 如果@Resource注解没有指定name属性,那么会先判断当前注入点名字(属性名字或方法参数名字)是不是存在Bean,如果存在,则直接根据注入点名字取获取bean,如果不存在,则会走@Autowired注解的逻辑,会根据注入点类型去找Bean

3.1 AutowiredAnnotationBeanPostProcessor的postProcessProperties 对于@Autowired @Value @Inject的处理

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    
    
	// 3.1.01 封装符合注解的元数据 element
	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;
}

// 3.1.02 封装元数据的方法
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    
    
	// 3.1.03 判断是否有Autowired Value Inject注解
	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    
    
		return InjectionMetadata.EMPTY;
	}

	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;

	do {
    
    
		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
		// 3.1.03 与@Resource不一样 如果是static field或者方法 不会thorw Exception
		ReflectionUtils.doWithLocalFields(targetClass, field -> {
    
    
			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
			if (ann != null) {
    
    
				if (Modifier.isStatic(field.getModifiers())) {
    
    
					if (logger.isInfoEnabled()) {
    
    
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				// (!ann.containsKey(this.requiredParameterName) ||
				// this.requiredParameterValue == ann.getBoolean(this.requiredParameterName))
				// 3.1.04 没有required 或者 required=true的布尔值
				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))) {
    
    
				if (Modifier.isStatic(method.getModifiers())) {
    
    
					if (logger.isInfoEnabled()) {
    
    
						logger.info("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				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));
			}
		});

		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);
	// 3.1.05 封装成element返回
	return InjectionMetadata.forElements(elements, clazz);
}

// 3.1.06 注入 inject内的resolveDependency方法
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable 		String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
    
    
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
    
    
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
    
    
		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
    
    
		// 3.1.07 如果是lazy 绑定代理 使用时注入 result就是绑定代理的对象
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
    
    
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

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

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
    
    
		// 3.1.08 根据名字和type判断是否该bean
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
    
    
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		// 3.1.09 获取@Value的value属性值
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		if (value != null) {
    
    
			// 3.1.10 @Value("${xxx.kk}") value属性值会进到下面的if里
			if (value instanceof String) {
    
    
				// 3.1.11 从environment拿到数据
				String strVal = resolveEmbeddedValue((String) value);
				BeanDefinition bd = (beanName != null && containsBean(beanName) ?
						getMergedBeanDefinition(beanName) : null);
				// 3.1.12 会判断strVal是不是EL表达式 不是则返回 是则走EL表达式逻辑
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			try {
    
    
				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
			}
			catch (UnsupportedOperationException ex) {
    
    
				// A custom TypeConverter which does not support TypeDescriptor resolution...
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}
		}
		// 3.1.13 针对注入的类型是StreamDependencyDescriptor,array,collection,map的处理
		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
    
    
			return multipleBeans;
		}
		// 3.1.14 getBeanNamesForType通过type找符合条件的bean Map<key, value> key是beanName value是符合条件的bean或者class 这里只负责找
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
    
    
			// 如果没找到 并且是required的 抛异常NoSuchBean
			if (isRequired(descriptor)) {
    
    
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
    
    
			// 3.1.15 (一)确定是否为@Primary
			// (二) 确定@Priority 优先级走高的
			// (三) matchName通过name拿到一个
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
    
    
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
    
    
					return descriptor.resolveNotUnique(descriptor.getResolvableType(), 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);
		}
		// 如果是class类型 则实例化赋值
		if (instanceCandidate instanceof Class) {
    
    
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		Object result = instanceCandidate;
		if (result instanceof NullBean) {
    
    
			if (isRequired(descriptor)) {
    
    
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			result = null;
		}
		if (!ClassUtils.isAssignableValue(type, result)) {
    
    
			throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
		}
		return result;
	}
	finally {
    
    
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

**总结一下@Autowired @Value

  1. 找到需要注入点 封装element
  2. 先判断是否为@Value 然后去environment拿值 如果是EL表达式 则执行表达式
  3. 然后才到了@Autowired这里
  4. 通过type类型寻找符合条件的bean或者class
  5. find出来多个后 判断是否有@Primary
  6. 再判断是否有@Priority 选优先级多最高的 (优先级设置的数字不能一样 会抛Multiple beans found with the same priority异常)
  7. class的话 实例化最后return**

猜你喜欢

转载自blog.csdn.net/weixin_45657738/article/details/109232695