SpringBoot扩展篇:Spring注入 @Autowired & @Resource

1. 概述

1.1 职责

@Autowired注入是由AutowiredAnnotationBeanPostProcessor完成的。
@Resource注入是由CommonAnnotationBeanPostProcessor完成的。
由于两种方式代码重复率太高,原理基本一致,下面我们主要以AutowiredAnnotationBeanPostProcessor源码分析为主。

1.2 流程概述

AutowiredAnnotationBeanPostProcessor负责属性、方法的注入。
分为两个流程:

  1. 注册元数据:先将要注入的字段和方法组成元数据,放入缓存中。
  2. 赋值:通过缓存中的描述信息从beanFactory中获取bean,字段和方法注入。

2. Demo

AutoObjectA

@Component
public class AutoObjectA {

    @Autowired
    private AutoObjectB autoObjectB;
    
}

AutoObjectB

@Component
public class AutoObjectB {

}

3. AutowiredAnnotationBeanPostProcessor注册

在创建AnnotationConfigServletWebServerApplicationContext的时候,就已经注册了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor。
SpringBoot 源码解析2:启动流程

AnnotationConfigUtils#registerAnnotationConfigProcessors

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	if (beanFactory != null) {
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
					AnnotationConfigUtils.class.getClassLoader()));
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}

	return beanDefs;
}

4. 注册元数据

SpringBoot 源码解析7:Bean的创建② AbstractAutowireCapableBeanFactory#createBean

在doCreateBean方法源码中,我们可以知道,在实例化bean之后,会通过applyMergedBeanDefinitionPostProcessors方法回调MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition。

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof MergedBeanDefinitionPostProcessor) {
			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}
}

AutowiredAnnotationBeanPostProcessor继承了MergedBeanDefinitionPostProcessor
在这里插入图片描述
元数据的注册的核心逻辑就在AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

4.1 AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

通过findAutowiringMetadata方法找到需要注入的元数据,然后还会检查一下成员变量。
暂时不知道checkConfigMembers的作用。

4.2 AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	// Fall back to class name as cache key, for backwards compatibility with custom callers.
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// Quick check on the concurrent map first, with minimal locking.
	InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
	if (InjectionMetadata.needsRefresh(metadata, clazz)) {
		synchronized (this.injectionMetadataCache) {
			metadata = this.injectionMetadataCache.get(cacheKey);
			if (InjectionMetadata.needsRefresh(metadata, clazz)) {
				if (metadata != null) {
					metadata.clear(pvs);
				}
				metadata = buildAutowiringMetadata(clazz);
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}
  1. 做了一个缓存injectionMetadataCache,将注入信息的流程与注入流程分开,注入时直接从缓存中获取信息。
  2. pvs为已经注入的属性,metadata.clear(pvs)会清除掉这些信息,不会重复注入。

4.3 AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata


private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

private String requiredParameterName = "required";

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.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	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<>();
		// 1. 先扫描方法上面的注入注解
		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;
				}
				// 是否必须注入,默认为true,找不到bean就会抛出异常
				boolean required = determineRequiredStatus(ann);
				// 注册
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});
		
		// 2. 再扫描方法上面的注入注解
		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);

	return InjectionMetadata.forElements(elements, clazz);
}

这是获取需要注入的元数据的核心方法

  1. 支持的注入注解包含Autowired、Value、Inject。
  2. 不支持静态注入,因为静态属于类的信息。
  3. 将方法注入的元数据放入到前面,所以方法先注入,后面字段注入会覆盖方法注入。
  4. 字段注入创建的是AutowiredFieldElement, 方法注入创建的是AutowiredMethodElement。字段注入和方法注入的逻辑基本一样的,后面讲解以demo中的字段注入为例。
  5. 最终,将要注入的信息封装到InjectionMetadata,完成注入信息的注册。
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
	return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
}

5. 字段注入逻辑

AbstractAutowireCapableBeanFactory#populateBean方法负责对bean的属性的初始化。回调了InstantiationAwareBeanPostProcessor#postProcessProperties。

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
	if (pvs == null) {
		pvs = mbd.getPropertyValues();
	}
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}
				pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					return;
				}
			}
			pvs = pvsToUse;
		}
	}
}

每次调用postProcessProperties会传入PropertyValues

5.1 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;
}

第二次调用findAutowiringMetadata从缓存中获取要注入的元素信息,并且将已经注入成功的pvs删除掉。

5.2 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

@Override
protected void inject(Object bean, @Nullable String beanName, @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,也就是字段所对应的bean
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			// 创建bean依赖的bean失败
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			// 如果没有添加缓存,那么就会添加缓存
			if (!this.cached) {
				if (value != null || this.required) {
					this.cachedFieldValue = desc;
					// 注册bean的依赖关系
					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;
			}
		}
	}
	// 设置属性的值
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}
}
  1. 这是@Autowired注解字段注入的实现逻辑。将依赖的bean的描述信息封装在DependencyDescriptor 中,通过beanFactory.resolveDependency解决依赖,方法的返回值就是所依赖的bean。
  2. cached:缓存了bean的依赖信息。
  3. 最终通过反射,完成了字段的初始化。

总结:beanFactory.resolveDependency方法获取到依赖的bean,通过反射field.set(bean, value)对字段赋值。

5.3 解决依赖关系 DefaultListableBeanFactory#doResolveDependency

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

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

		Class<?> type = descriptor.getDependencyType();
		// 对@Value注解进行解析,返回的是value值
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		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());
			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()));
			}
		}
		
		// 这里是对集合、数组、Map注入的支持
		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) {
			// 如果根据type匹配多个,那么就解析@Primary或者Order匹配
			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.
			// By Type只能匹配到一个
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			// 这里By name取bean实例
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		Object result = instanceCandidate;
		if (result instanceof NullBean) {
			// 校验bean是否与类型匹配
			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);
	}
}
  1. getAutowireCandidateResolver().getSuggestedValue():对@Value注解注入的支持。
  2. resolveMultipleBeans:对数组、集合、Map注入的支持。
  3. findAutowireCandidates:返回所有匹配的信息,返回一个map,key为beanName,如果依赖bean创建完毕,value就为依赖bean,否则就是beanClass。
    为什么说@Autowired注解是By Type注入的呢?原因就在DefaultListableBeanFactory#findAutowireCandidates这个方法!
    在这里插入图片描述BeanFactoryUtils.beanNamesForTypeIncludingAncestors通过给定的类型,找到所有的对应的beanName,然后在通过beanName去获取Bean。
    不要将@Autowired注入方式简简单单的理解为 通过类型直接匹配bean。在Spring中,不管是bean的注册(保存在beanDefinitionMap中,key为beanName)还是单例bean的保存(singletonObjects,key为beanName),他们的身份标识都为beanName,就算用户没有指定beanName,Spring中内置了BeanNameGenerator自动生成bean的名称。
  4. 如果有多个匹配的bean,那么就通过determineAutowireCandidate取最合适的那个,由@Primary注解和@Order决定。
  5. 上述说过,By Type匹配的时候,依赖bean还没有创建成功,返回的就是type,那么就会通过descriptor.resolveCandidate创建真正的bean。创建bean毫无疑问就要调用beanFactory.getBean。
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
		throws BeansException {

	return beanFactory.getBean(beanName);
}
  1. 这个方法的本身就是By Type注入。如果需要By Name 注入,就要调用AbstractAutowireCapableBeanFactory#resolveBeanByName。

5.4 Autowired注入逻辑总结

核心方法是doResolveDependency。首先是By Type取出所有的beanName,然后通过beanName从beanFactory取出bean,最后设置属性中。

6. @Resource注入方式

读了上述内容,我们知道了注入方法。那么,@Resource的注入方式是什么呢?
那么就要看CommonAnnotationBeanPostProcessor源码了。

6.1 Demo

@Component
public class ResourceA {
    @Resource
    private ResourceB resourceB;
}

@Component
public class ResourceB {
}

字段注册和Autowired逻辑基本一致

6.2 Resource注入逻辑

调用链:

  1. CommonAnnotationBeanPostProcessor#postProcessProperties
  2. InjectedElement#inject
  3. CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
  4. CommonAnnotationBeanPostProcessor#getResource
  5. CommonAnnotationBeanPostProcessor#autowireResource

6.3 CommonAnnotationBeanPostProcessor#autowireResource

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();
		// 判断为True,就需要By Type的方式解决依赖
		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 {
			// 这里是By Name的方式解决依赖
			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;
}
  1. 判断条件
    条件一:fallbackToDefaultTypeMatch默认为true。
    在这里插入图片描述
    条件二:是否使用默认名称。如果用户指定了依赖的bean的名称,那么就认为指定的bean必然要存在,isDefaultName就为false,就需要By Name取获取依赖bean。否则就使用字段的名称。
    在这里插入图片描述

    条件三:beanName没有对应的实例或者beanDefinition。如果没有,那么就By Type去解决依赖关系。为什么这样呢?比如应该是

@Override
public boolean containsBean(String name) {
	String beanName = transformedBeanName(name);
	if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
		return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
	}
	// Not found -> check parent.
	BeanFactory parentBeanFactory = getParentBeanFactory();
	return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}
  1. 只有满足同时上述三个条件才会By Type获取bean。所以也兼容 By Type注入。
  2. 为什么要有条件三呢?
    因为ResourceB对应的bean被默认的BeanNamegenerator生成的beanName为"resourceB"。兼容了即使用户写错了变量名称,也要注入成功。比如:
@Resource
private ResourceB b;

6.4 结论

所以,@Resource注入逻辑如下:

  1. 如果用户指定了beanName,那么就通过beanName注入。
  2. 如果用户没有指定beanName,注入的字段名称存在对应的bean,那么就By Name注入。如果不存在对应的bean就是 By Type注入。
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Spring Boot中,使用多线程处理任务时,有时会遇到无法使用@Autowired注入Bean的问题。这是因为多线程环境下,不同的线程可能无法直接访问容器中的Bean。 要解决这个问题,可以使用以下方法: 1. 通过ConfigurableApplicationContext获取Bean 可以通过ConfigurableApplicationContext对象的getBean方法来手动获取Bean,而不使用@Autowired注解。代码示例: ```java @Autowired private ConfigurableApplicationContext context; // 在多线程任务中获取Bean MyBean myBean = (MyBean) context.getBean("myBean"); ``` 2. 使用@Bean和@Scope注解 可以在Bean的定义上,使用@Bean和@Scope注解指定作用域为"prototype",以确保每个线程都可以获取到一个全新的Bean实例。代码示例: ```java @Configuration public class MyConfig { @Bean @Scope("prototype") public MyBean myBean() { return new MyBean(); } } ``` 然后在需要使用多线程处理任务的类中,使用注解@Autowired获取Bean。代码示例: ```java @Component public class MyTask { @Autowired private MyBean myBean; // 多线程任务代码 } ``` 通过以上两种方法,可以在Spring Boot中实现多线程处理任务,并成功注入Bean。 ### 回答2: 在Spring Boot中,使用多线程处理任务时,有时会遇到无法注入@Autowired Bean的问题。这通常是因为多线程任务是在一个独立的线程中执行的,而不是由Spring容器管理的线程。 要解决这个问题,可以尝试使用以下方法: 1. 在创建线程时手动注入Bean:在创建线程的地方,使用ApplicationContext的getBean方法手动获取需要注入的Bean,并将其传递给线程。这样就可以确保在多线程任务中使用正确的Bean实例。 2. 使用@Configurable注解:在多线程任务的类上添加@Configurable注解,然后在需要注入的地方使用@Autowired注解。这样Spring将会为这个类创建代理对象,并在需要注入Bean的地方自动注入相关的Bean。 3. 使用ThreadFactory和ThreadLocal:可以通过自定义ThreadFactory来创建线程,并在其中使用ThreadLocal来保存需要注入的Bean。然后,在执行任务的线程中,通过ThreadLocal获取需要的Bean实例。 需要注意的是,对于使用多线程处理任务的情况,一定要谨慎处理并发问题。确保多个线程之间不会产生数据竞争或其他并发问题,例如使用锁或其他同步机制来保护共享数据。 总而言之,处理Spring Boot中多线程任务无法注入Bean的问题可以通过手动注入Bean、使用@Configurable注解或使用ThreadFactory和ThreadLocal来解决。需要根据具体情况选择合适的方法,并注意处理并发问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值