本章是属性注入的详细分析
默认情况下,spring不会主动给bean注入是属性的,开发者需要自己配置,首先明确的是对象有哪些属性需要注入,注入的类型是按照类型还是按照名称。之前这些可以在xml文件中配置,但是在开发中最好是通过注解的方式实现,所以用到了@autowired,@resource注解,需要注入的属性,使用注解标注即可。spring是怎么知道对象中哪些属性用注解标注了呢?
进入方法AbstractAutowireCapableBeanFactory#doCreateBean,在创建完实例之后,有一步调用处理器的postProcessMergedBeanDefinition方法,属性注入之前对bd的最后操作。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
bean处理器中有两个是用来处理@autowired,@resource注解的
两个处理器的逻辑大致相似,本文以AutowiredAnnotationBeanPostProcessor处理器为例进行分析,下面进入到AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition方法
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// InjectionMetadata 保存了这个bean的需要注入的属性
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
构建保存实例属性的对象InjectionMetadata。
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 从缓存中取数据
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 如果数据是null 或者数据中保存的对象和clazz对不上了,就需要刷新,进入方法
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;
}
从缓存中取数据,如果没有就直接构建对象。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 是否这个类的属性有用注解标注的属性(@autowired @value),如果没有直接返回空了
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<>();
// 利用反射得到这个类的属性,根据属性得到属性上的注解
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;
}
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);
// 创建InjectionMetadata对象
return InjectionMetadata.forElements(elements, clazz);
}
根据反射得到类的属性,如果属性有@autowired注解,就先将该属性信息创建AutowiredFieldElement对象,得到所有的属性集合,创建InjectionMetadata信息。可以看到InjectionMetadata保存了目标bean的class信息和需要注入的属性集合。注意,关于属性和方法,静态的都不能注入。
下面开始进入属性注入AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 如果没有实例,根本不用注入了,直接返回了
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 实例化之后的操作,如果返回的是false,就不在注入了。
// 实例化处理器的实例化之后的处理器方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
//先看bd中是否已经设置了需要注入的属性。通常有值的都是xml配置的,或者是自定义的bd.
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 默认是不注入的AUTOWIRE_NO
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通过名称找到 key: propertyName, value:bean
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通过类型找
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
// 无论是按照名称注入还是按照类型注入,会把实例和属性名称保存在newPvs中,现在还没有注入属性呢
pvs = newPvs;
}
// 上面的逻辑过后,newPvs中的集合中对象类似一个k-v对,key是属性,value是注入的对象。
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 下面的逻辑是注解的方式实现注入。处理器处理属性。
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里的是处理属性的处理器,其实就是保存@autowired和@resource注解的处理器。这里有注入逻辑,通过field,得到相应的bean,最后通过反射给属性赋值。
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 通过名称或类型的在这步赋值。
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
先梳理下流程,从bd中找到注入的属性,根据注入的类型,从beanFactory中取出对应的对象。放入到MutablePropertyValues 中,最后通过applyPropertyValues方法,反射给属性赋值。如果是通过注解的方式处理注入的,是通过处理器,即上面已经提到的处理器。进行处理。
由于支持注解开发模式和xml文件配置的开发模式。所以这块代码看起来混乱。可以这么理解,注解的处理是在处理器中,xml中的已经保存在了bd中,从bd中取出PropertyValues,最后用beanWrapper进行属性注入,本质是反射调用set方法。而注解的本质是属性的反射赋值
下面看下注解方式是如何注入的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;
}
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()) {
// 遍历需要注入的属性,分别注入。
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
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 {
// 从容器中找值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, 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;
}
}
}
// 通过反射,调用属性的设置
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
是核心方法。
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
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 {
// 不同类型走不同的逻辑
// 一般情况下,走这块:
// 从属性找是否有@lazy注解,有的话,就创建一个代理对象懒注册。
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);放用来找Lazy注解,实现懒加载。用到的时候在取找对象。
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
"BeanFactory needs to be a DefaultListableBeanFactory");
final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
TargetSource ts = new TargetSource() {
@Override
public Class<?> getTargetClass() {
return descriptor.getDependencyType();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() {
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
if (target == null) {
Class<?> type = getTargetClass();
if (Map.class == type) {
return Collections.emptyMap();
}
else if (List.class == type) {
return Collections.emptyList();
}
else if (Set.class == type || Collection.class == type) {
return Collections.emptySet();
}
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
"Optional dependency not present for lazy injection point");
}
return target;
}
@Override
public void releaseTarget(Object target) {
}
};
ProxyFactory pf = new ProxyFactory();
pf.setTargetSource(ts);
Class<?> dependencyType = descriptor.getDependencyType();
if (dependencyType.isInterface()) {
pf.addInterface(dependencyType);
}
return pf.getProxy(beanFactory.getBeanClassLoader());
}
如果不用懒加载,就直接总bean工厂中找对象。doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
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注解。
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
// 处理value注解
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;
// 如果能选出多个候选的bean
if (matchingBeans.size() > 1) {
// 过滤出一个合适的bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
// 如果没选出来,这个bean优势必须的,直接抛异常
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);
}
// 实例化bean
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);
}
}
解析@Value注解的。
如果类型是复杂的如,数组,集合,map,处理。
普通类型的。通过findAutowireCandidates找出所有合适的。在通过determineAutowireCandidate找出用哪个。
findAutowireCandidates:
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);
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;
}
}
}
// 这里进行了筛选,
// isAutowireCandidate是筛选逻辑;
// 里面有反射的条件筛选,同时如果有@Qualifiers注解,检查是否符合要求
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 如果没有合适的,那么就放宽要求。
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// 考虑泛型不用精确匹配。
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
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;
}
这块有泛型的匹配。如果要注入的类型没有泛型例如private HelloService helloService ,那么匹配的时候会加上泛型适配符HelloService,?>,这样所有同类型的泛型都符合要求。但是如果注入的是有明确泛型的比如:HelloService
具体还是看这篇文章。【小家Spring】细说Spring IOC容器的自动装配(@Autowired),以及Spring4.0新特性之【泛型依赖注入】的源码级解析
如果有多个符合怎么办呢?
通过方法determineAutowireCandidate筛选。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
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();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
// 找Primary的,但让设置了过个肯定是报错的。如果没有设置,返回null
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
if (isPrimary(candidateBeanName, beanInstance)) {
// 如果都标注了,就保存了
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
// 标注了Priority,有了优先级,数值越低,优先级越高。当然了,如果没有标注,返回null,标记值一样报错。
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();
if (beanInstance != null) {
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());
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
return highestPriorityBeanName;
}
// 如果还不能区分,就按照属性的名称和bean的名称比较,相等的为符合的。
protected boolean matchesBeanName(String beanName, @Nullable String candidateName) {
return (candidateName != null &&
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}
在都符合的时候,通过人为干预,选取合适的。
先进行@primary的筛选,指定了,有指定的,指定多了就报错;没有指定,继续下面的。
通过优先级,数值低,优先级高,没有指定,还是无法筛选,返回null,优先级一样,报错。
还不行,按照属性的名称匹配。,还不行,spring也不知道用哪个了,返回null.
如果是必须的,抛异常throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
所以按照类型注入什么时候会报错呢?就是找到了多个,没有找到就返回null了。
使用@Resource注入,需要明确是@Resource不是Spring的注解,是JSR标准
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties
直接看这个注入的方法了,其实在依赖输入之前,postProcessMergedBeanDefinition这个方法会进行依赖注入的解析,保存缓存中,在postProcessProperties是从缓存找取,执行注入逻辑。所以直接看postProcessProperties方法也无妨。
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;
}
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata
解析需要注入的信息
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 得到所有的属性信息
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 兼容其他注解
。。。。。。
// 我们只关注Resource注解的。
else if (field.isAnnotationPresent(Resource.class)) {
// 静态的属性不能注入
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
// 将属性封装为ResourceElement
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 兼容其他注解
。。。。。
// 只看Resource注解
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
// 静态的方法不能注入
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
// 方法参数个数不是1的会抛异常。
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
// 封装为ResourceElement
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);
return InjectionMetadata.forElements(elements, clazz);
}
解析注解:
注入逻辑:
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()) {
// 遍历InjectedElement集合,调用InjectedElement 的注入方法。
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
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通过该方法得到值;
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
//这里有一个懒加载的操作。
// 如果使用@lazy注解标注了,会给创建一个代理,只有再使用的时候才会取bean工厂中找bean
//非懒加载的会立刻执行找bean的逻辑,返回结果。懒加载是先返回要给代理,等调用放的时候再去执行找bean的过程。
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
// 如果是属性,这里是注解value的值,没有指定,就是属性的名称
// 如果是方法,javabean标准,是属性名称;不是javaBean标准,则是方法名称。
String name = element.name;
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
// 如果按照名称找,但是名称没有,就按类型找。
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;
}
按照名称找不到,就会按照类型找。
public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
super(member, pd);
Resource resource = ae.getAnnotation(Resource.class);
// Resource 指定的bean名称
String resourceName = resource.name();
Class<?> resourceType = resource.type();
this.isDefaultName = !StringUtils.hasLength(resourceName);
// 如果使用默认的名称
if (this.isDefaultName) {
// 属性名称或者方法名称
resourceName = this.member.getName();
// 如果是方法,兵器是set开头,长度>3,是javaBean规范
// 内省机制找到属性名。否则还是方法名称。
if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
resourceName = Introspector.decapitalize(resourceName.substring(3));
}
}
else if (embeddedValueResolver != null) {
resourceName = embeddedValueResolver.resolveStringValue(resourceName);
}
if (Object.class != resourceType) {
checkResourceType(resourceType);
}
else {
// No resource type specified... check field/method.
resourceType = getResourceType();
}
this.name = (resourceName != null ? resourceName : "");
this.lookupType = resourceType;
String lookupValue = resource.lookup();
this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
Lazy lazy = ae.getAnnotation(Lazy.class);
this.lazyLookup = (lazy != null && lazy.value());
}
关于根据名称找的问题;如果注解给了名称,使用该名称,没有给,就用属性自己的。如果是注释在方法上,如果是符合JavaBean规范,那么用的将是属性名称,否则用的是方法名称。
有个问题;静态的属性和方法都还不能用注解,那如果就是想用静态的怎么版呢?
就是通过普通方法给静态属性赋值
@Component
public class UserHelper {
static UCClient ucClient;
@Autowired
public void setUcClient(UCClient ucClient) {
UserHelper.ucClient = ucClient;
}
}
但是想想工具类都是静态的,不用交给spring管理。
SmartInitializingSingleton该接口会在所有的bean都实例化之后调用
@Component
public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* 当所有的单例Bena初始化完成后,对static静态成员进行赋值
*/
@Override
public void afterSingletonsInstantiated() {
// 交给工厂,给我注如,
beanFactory.autowireBean(new UserHelper());
}
}
这样该类就不用加@Component注解。工具类交给beanFactory,让工厂注入。
public class UserHelper {
static UCClient ucClient;
@Autowired
public void setUcClient(UCClient ucClient) {
UserHelper.ucClient = ucClient;
}
}
或者这样:
@Component
public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {
@Autowired
private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;
// 就是让处理器给注入
@Override
public void afterSingletonsInstantiated() {
autowiredAnnotationBeanPostProcessor.processInjection(new UserHelper());
}
}