AutowiredAnnotationBeanPostProcessor — это постпроцессор Spring, который обрабатывает аннотации @Autowired и @Value.
1. Триггерный метод
- Контейнер Spring вызывает AutowiredAnnotationBeanPostProcessor после создания экземпляра каждого компонента.
postProcessMergedBeanDefinition
чтобы узнать, есть ли у bean-компонента аннотация @Autowired. - Spring вызывает, когда создается экземпляр каждого bean-компонента
populateBean
При выполнении внедрения свойств, то есть вызовеpostProcessPropertyValues
чтобы узнать, есть ли у bean-компонента аннотация @Autowired.
2. Конструктор
public AutowiredAnnotationBeanPostProcessor() {
//后置处理器将处理@Autowire注解
this.autowiredAnnotationTypes.add(Autowired.class);
//后置处理器将处理@Value注解
this.autowiredAnnotationTypes.add(Value.class);
try {
//后置处理器将处理javax.inject.Inject JSR-330注解
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.
}
}
В-третьих, метод инъекции
//处理类中的属性,属性注入
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//获取指定类中autowire相关注解的元信息
<1> InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//对Bean的属性进行自动注入
<2> 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;
}
Этот метод вызывается при внедрении атрибута populateBean.pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
одна из конкретных реализаций.
Код в предназначен для получения соответствующей аннотационной информации от bean-компонента вAutowiredAnnotationBeanPostProcessor
Здесь нужно найти поля, аннотированные с помощью @Value и @Autowired, а затем инкапсулировать соответствующую информацию вInjectionMetadata
. код показывает, как показано ниже:
//获取给定类的autowire相关注解元信息
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.
//首先从容器中查找是否有给定类的autowire相关注解元信息
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) {
//解析给定类autowire相关注解元信息
metadata.clear(pvs);
}
//解析给定类autowire相关注解元信息
metadata = buildAutowiringMetadata(clazz);
//将得到的给定类autowire相关注解元信息存储在容器缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
ПосмотримbuildAutowiringMetadata
Подробный код:
//解析给定类autowire相关注解元信息
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//创建一个存放注解元信息的集合
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
//递归遍历当前类及其所有基类,解析全部注解元信息
do {
//创建一个存储当前正在处理类注解元信息的集合
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
//利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//获取给定字段上的注解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
//如果给定字段是静态的(static),则直接遍历下一个字段
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//判断注解的required属性值是否有效
boolean required = determineRequiredStatus(ann);
//将当前字段元信息封装,添加在返回的集合中
currElements.add(new AutowiredFieldElement(field, required));
}
});
//利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//获取给定方法上的所有注解
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//如果方法是静态的,则直接遍历下一个方法
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
//如果方法的参数列表为空
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
//判断注解的required属性值是否有效
boolean required = determineRequiredStatus(ann);
//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//将方法元信息封装添加到返回的元信息集合中
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//将当前类的注解元信息存放到注解元信息集合中
elements.addAll(0, currElements);
//获取给定类的父类
targetClass = targetClass.getSuperclass();
}
//如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
Комментарии к этому коду очень понятные, на этом шаге получается метаинформация об аннотациях, связанных с autowire, в указанном классе.
ps: здесь вы можете видеть, что аннотация @Autowired не поддерживает статическую модификацию
ПосмотримpostProcessPropertyValues
Конкретная логика внедрения в метода:
//InjectionMetadata.java
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);
}
}
}
Это не настоящий метод закачки, продолжаем отслеживатьelement.inject(target, beanName, pvs);
//InjectionMetadata.java
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();
}
}
}
Этоelement.inject()
Оригинальный метод, он также имеет два метода, реализованных подклассами, как показано на рисунке:
AutowiredAnnotationBeanPostProcessor
конкретная реализация.
3.1, полевая инъекция
Давайте сначала посмотрим на инъекцию поля:
//AutowiredAnnotationBeanPostProcessor.java
@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
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 {
//核心!获取注入的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
//线程同步,确保容器中数据一致性
synchronized (this) {
//如果字段的值没有缓存
if (!this.cached) {
//字段值不为null,并且required属性为true
if (value != null || this.required) {
this.cachedFieldValue = desc;
//为指定Bean注册依赖Bean
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
//如果容器中有指定名称的Bean对象
if (beanFactory.containsBean(autowiredBeanName)) {
//依赖对象类型和字段类型匹配,默认按类型注入
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//创建一个依赖对象的引用,同时缓存
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
//如果获取的依赖关系为null,且获取required属性为false
else {
//将字段值的缓存设置为null
this.cachedFieldValue = null;
}
//容器已经对当前字段的值缓存
this.cached = true;
}
}
}
//如果字段值不为null
if (value != null) {
//显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
ReflectionUtils.makeAccessible(field);
//为字段赋值
field.set(bean, value);
}
}
Этот код легко понять, получить значение для ввода из аннотации @Value/@Autowired, а затем использовать отражение, чтобы установить его в поле.
Дело в том, как получить значение, которое будет введено из аннотации, давайте посмотрим на основной код.value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
//DefaultListableBeanFactory.java
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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//真正获取值的代码
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
Выслеживать:
//DefaultListableBeanFactory.java
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 针对给定的工厂给定一个快捷实现的方式,例如考虑一些预先解析的信息
// 在进入所有bean的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式。
// 子类可以覆盖此方法
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取字段属性的类型
Class<?> type = descriptor.getDependencyType();
//拿到@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());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//如果标识@Autowired注解的属性是复合类型,如Array,Collection,Map,
// 从这个方法获取@Autowired里的值
<1> Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//如果标识@Autowired注解的属性是非复合类型,
// 从这个方法获取@Autowired里的值
<2> Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//如果没有符合该类型的Bean
if (matchingBeans.isEmpty()) {
// 没有找到,检验 @autowire 的 require 是否为 true
if (isRequired(descriptor)) {
//抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果符合该类型的Bean有多个
if (matchingBeans.size() > 1) {
//挑选出最优解
<3> autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//抛出异常
return descriptor.resolveNotUnique(type, 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);
}
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);
}
}
Этот код выглядит длинным, но на самом деле его довольно легко понять. Общий процесс таков:
Получите соответствующие bean-компоненты из контейнера IOC в соответствии с типом поля.Если их несколько, выберите оптимальный.
Давайте посмотрим на конкретную логику ниже.
3.1.1, : @Autowired внедряет массив коллекций, например Map.List
Давайте сначала посмотрим на логику внедрения @Autowired в массив коллекции:
//DefaultListableBeanFactory.java
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
//如果@Autowired标识的是数组类型的属性
if (type.isArray()) {
//获取数组的内容类型
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve();
if (resolvedArrayType != null && resolvedArrayType != type) {
type = resolvedArrayType;
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
//通过类型去IOC容器内择取符合的Bean都是使用这个方法
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());
//将得到的Bean的候选者们转换为属性类型,如从set转换为Array,List等
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (getDependencyComparator() != null && result instanceof Object[]) {
Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
//获取Collection的泛型
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
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 (getDependencyComparator() != null && result instanceof List) {
Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));
}
return result;
}
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
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;
}
}
3.1.2, : @Autowired внедряет неколлективные массивы, то есть обычные классы, такие как Service
//DefaultListableBeanFactory.java
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//从IOC容器中获取所有的符合类型的BeanName,存入候选数组
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//首先从容器自身注册的依赖解析来匹配,Spring容器自身注册了很多Bean的依赖,
//当使用者想要注入指定类型的Bean时,会优先从已注册的依赖内寻找匹配
for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
//如果注册的依赖Bean类型是指定类型的实例或是其父类,接口,则将其作为候选者,注册依赖的类型不会重复
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//遍历候选数组
for (String candidate : candidateNames) {
//候选Bean不是自引用(即要注入的类不能是类本身,会触发无限递归注入)
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// 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;
}
Этот комментарий к коду написан очень четко, давайте продолжим его рассматриватьaddCandidateEntry
метод, который должен поместить экземпляр Bean в коллекцию кандидатов
//DefaultListableBeanFactory.java
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
//当@Autowired标识的是容器类型的属性,生成的依赖描述类型是MultiElementDescriptor ,
//因此所有的候选者均是合格的,所以会当场实例化他们。而如果属性的类型非容器,那么可能是多个候选者中挑一个,
//此时实例化他们所有就不合适了,最终会把合格的那个实例化,如果没有合格的则不实例化,
//提前实例化对Bean的很多方面有影响,比如AOP,EarlyReference等 */
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(candidateName, getType(candidateName));
}
}
Здесь будет вызываться метод doGetBean() для создания экземпляра Bean.
: выберите оптимальное решение из нескольких вариантов
Если есть несколько bean-компонентов, полученных из контейнера IOC в соответствии с типом, вам нужно вызватьdetermineAutowireCandidate(matchingBeans, descriptor)
Метод выбора оптимального решения.
Код:
//DefaultListableBeanFactory.java
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//根据@Primary注解来择取最优解
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//根据@Order,@PriorityOrder,及实现Order接口的序号来择取最优解
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//如果通过以上两步都不能选择出最优解,则使用最基本的策略
//首先如果这个类型已经由Spring注册过依赖关系对,则直接使用注册的对象,
//候选者集合是LinkedHashMap,有序Map集合,容器注册的依赖对象位于LinkedHashMap的起始位置
//如果没有注册过此类型的依赖关系,则根据属性的名称来匹配,、
//如果属性名称和某个候选者的Bean名称或别名一致,那么直接将此Bean作为最优解
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
Эта часть логики относительно проста и состоит из 3 шагов:
- Выберите оптимальное решение по аннотации @Primary
- Выберите оптимальное решение в соответствии с @Order, @PriorityOrder и порядковым номером, реализующим интерфейс Order.
- Согласно правилам Spring по умолчанию
Давайте проанализируем эти шаги один за другим, давайте посмотрим на первый:
Выберите оптимальное решение по аннотации @Primary
//DefaultListableBeanFactory.java
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
//候选者可以是父容器内的标识了@Primary的Bean,也可以是当前容器的。SpringMVC容器将Spring容器作为父容器
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
//此处确保同一个容器中同一个类型的多个Bean最多只有一个Bean标识了@Primary
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
//如果上一个@Primary的Bean是父容器的,则用当前容器的候选者覆盖之前的@Primary的Bean
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
Тогда посмотрите на второй:
Согласно @Order, @PriorityOrder
//DefaultListableBeanFactory.java
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
//不能同时存在两个最高优先级的序号
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
//使用优先级序号最小的Bean作为最优解
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
return highestPriorityBeanName;
}
резюме:
На этом этапе анализируется исходный код, введенный полем @Autowired.
Далее мы рассмотрим метод инъекции:
3.2, метод инъекций
//DefaultListableBeanFactory.java
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//如果属性被显式设置为skip,则不进行注入
if (checkPropertySkipping(pvs)) {
return;
}
//获取注入元素对象
Method method = (Method) this.member;
Object[] arguments;
//如果容器对当前方法缓存
if (this.cached) {
// Shortcut for avoiding synchronization...
//获取缓存中指定Bean名称的方法参数
arguments = resolveCachedArguments(beanName);
}
//如果没有缓存
else {
//获取方法的参数列表
Class<?>[] paramTypes = method.getParameterTypes();
//创建一个存放方法参数的数组
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
//获取容器的类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
//创建方法参数对象
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
//解析方法的输入参数,为方法参数创建依赖描述符
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
//根据容器中Bean定义解析依赖关系,获取方法参数依赖对象
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
//线程同步,以确保容器中数据一致性
synchronized (this) {
//如果当前方法没有被容器缓存
if (!this.cached) {
//如果方法的参数列表不为空
if (arguments != null) {
//为容器中缓存方法参数的对象赋值
Object[] cachedMethodArguments = new Object[paramTypes.length];
for (int i = 0; i < arguments.length; i++) {
cachedMethodArguments[i] = descriptors[i];
}
//为指定Bean注册依赖Bean
registerDependentBeans(beanName, autowiredBeans);
//如果依赖对象集合大小等于方法参数个数
if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
//为方法参数设置依赖对象
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
//如果容器中存在指定名称的Bean对象
if (beanFactory.containsBean(autowiredBeanName)) {
//如果参数类型和依赖对象类型匹配
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
//创建一个依赖对象的引用,复制给方法相应的参
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
//如果方法参数列表为null,则设置容器对该方法参数的缓存为null
else {
this.cachedMethodArguments = null;
}
//设置容器已经对该方法缓存
this.cached = true;
}
}
}
//如果方法参数依赖对象不为null
if (arguments != null) {
try {
//使用JDK的反射机制,显式设置方法的访问控制权限为允许访问
ReflectionUtils.makeAccessible(method);
//调用Bean的指定方法
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex){
throw ex.getTargetException();
}
}
}
Суммировать
Принцип аннотации @Autowired объясняется в одном предложении:
Сначала нужно найти все подходящие bean-компоненты из контейнера IOC в соответствии с типом, а затем выбрать наиболее подходящие bean-компоненты в соответствии с правилами по умолчанию @Primary, @Order, @PriorityOrder или Spring и внедрить их в поля с помощью отражения.