在《spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)》中分析了CommonAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition方法的作用,即是对类中的@Resources、@WebServiceRef、@EJB三个注解进行解析并缓存起来,以便后续执行postProcessProperties方法的时候用到缓存的信息。在spring启动过程中还有一个和CommonAnnotationBeanPostProcessor类相似的bean后置处理器,该类就是AutowiredAnnotationBeanPostProcessor,该bean后置处理器的作用是处理@Autowired、@Value、@Inject注解。
一、概述
前面说到AutowiredAnnotationBeanPostProcessor类是解析@Autowired注解的,那么该注解的作用是什么那,是怎么定义的那
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD,ElementType.PARAMETER,ElementType.FIELD,ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { /** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */ boolean required() default true; }
上面是该注解的定义,该注解的作用是自动注入,该注解是Spring提供的注解(@Resource、@WebServiceRef、@EJB均是java提供的)。
AutowriedAnnotationBeanPostProcessor要解析@Autowired注解那么按照前面分析的CommonAnnotationBeanPostProcessor和InitDestroyBeanPostProcessor两个类,必须要先有要解析的类型,也就是初始化解析的类型,看AutoworedAnnotationBeanPostProcessor的构造方法,
@SuppressWarnings("unchecked") public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.try { this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Inject",AutowiredAnnotationBeanPostProcessor..getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
上面是其默认的构造方法,可以看到向autowiredAnnotationTypes中加了三个注解:@Autowired、@Value、@Inject,其中@Inject是java中的注解,其余两个均是Spring提供的注解。那么这里其实是说明AutowiredAnnotationBeanPostProcessor类是解析这三个注解的,我们继续往下分析。
二、详述
1、方法概述
下面看AutoWiredAnnotationBeanPostProcessor类中的方法,
上面给出了AutoWiredAnnotationBeanPostProcessor类中的主要的方法,重点看postProcessMergedBeanDefinition和postProcessProperties方法,postProcessPropertyValue方法在前边已经说过该方法已经废弃了,调用的是postProcessProperties方法。
2、postProcessMergedBeanDefinition
该方法的作用是解析类中标记了@AutoWired、@Value、@Inject注解的属性和方法,下面看具体的方法定义,
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType,String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName,beanType,null); metadata.checkConfigMembers(beanDefinition); }
2.1、findAutowiringMetadata
下面看findAutowiringMetadata方法
private InjectionMetadata findAutowiringMetadata(String beanName,1)"> 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 (.injectionMetadataCache) { metadata = .injectionMetadataCache.get(cacheKey); if (metadata != ) { metadata.clear(pvs); }
//查找目标类clazz中的标识了@AutoWired、@Value、@Inejct注解 metadata = buildAutowiringMetadata(clazz); .injectionMetadataCache.put(cacheKey,metadata); } } } return metadata; }
从上面的代码中可以看出最终是把标识了@AutoWired、@Value、@Inject注解的方法或字段信息封装为Metadata然后放在了injectionMetadataCache中,重点看buildAutowiringMetadata方法,
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { autowiredAnnotationTypes中得值为 * @AutoWired org.springframework.beans.factory.annotation.Autowired * @Value org.springframework.beans.factory.annotation.Value * @Inject javax.inject.Inject * */ if (!AnnotationUtils.isCandidateClass(clazz,1)">.autowiredAnnotationTypes)) { InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; dofinal List<InjectionMetadata.InjectedElement> currElements = (); 判断字段上是否存在autowiredAnnotationTypes中的注解 ReflectionUtils.doWithLocalFields(targetClass,field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != ) { (Modifier.isStatic(field.getModifiers())) { (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } ; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field,required)); } }); 判断方法上是否存在autowiredAnnotationTypes中的注解 ReflectionUtils.doWithLocalMethods(targetClass,method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method,bridgedMethod)) { ; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); null && method.equals(ClassUtils.getMostSpecificMethod(method,clazz))) { (Modifier.isStatic(method.getModifiers())) { (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } if (method.getParameterCount() == 0) { (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod,clazz); currElements.add( AutowiredMethodElement(method,required,pd)); } }); elements.addAll(0,currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.); InjectionMetadata.forElements(elements,clazz); }
该代码比较多,主要是对目标类中的方法和字段信息进行了检查,判断是否标注了@AutoWired、@Value、@Inject三个注解,最后返回InjectionMetadata.forElements该方法是做什么的那,由于前边生成的对象是elements的对象,看elements对象的类型,
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
是一个ArrayList类型,泛型是InjectionMetadata.InejctedElement,下面看该方法,
static InjectionMetadata forElements(Collection<InjectedElement> elements,1)">return (elements.isEmpty() ? InjectionMetadata.EMPTY : InjectionMetadata(clazz,elements)); }
从上面的代码可以看到,最终是new了一个InjectionMetadata的实例。最终buildAutowiringMetadata方法返回的是一个InjectionMetadata的实例。
buildAutowiringMetadata方法执行完以后,在findAutowiringMetadata方法中,把返回的InjectionMetadata实例放入了injectionMetadataCache中,最终返回一个InjectionMetadata实例。
2.2、checkConfigMembers
在postProcessMergedBeanDefinition方法中的第二行代码即调用了checkConfigMembers方法
metadata.checkConfigMembers(beanDefinition);
该方法的定义如下,
void checkConfigMembers(RootBeanDefinition beanDefinition) { Set<InjectedElement> checkedElements = new LinkedHashSet<>(.injectedElements.size()); for (InjectedElement element : .injectedElements) { Member member = element.getMember(); beanDefinition.isExternallyManagedConfigMember(member)) { beanDefinition.registerExternallyManagedConfigMember(member); checkedElements.add(element); (logger.isTraceEnabled()) { logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element); } } } this.checkedElements = checkedElements; }
从上面的代码中可以看出首先new了一个checkedElements,使用的是injectedElements的长度,injectedElements是什么那,怎么赋值的那。在buildAutowiringMetadata方法的最后调用了InectionMetadata.forElements方法,在该方法中最后生成了一个InjectionMetadata对象,传入了elements对象,便是该对象。
checkConfiMembers方法主要是调用了beanDefintion.isExternallyManagedConfigMemgber方法,该方法暂时不讨论。
3、postProcessProperties
上面分析了postProcessMergedBeanDefinition方法后,我们知道该方法的作用就是收集类中的标注了@AutoWired、@Value、@Inject注解的字段或方法,那么postProcessProperties方法便是在进行赋值的时候调用的,
完成@AutoWired属性的注入 @Override PropertyValues postProcessProperties(PropertyValues pvs,Object bean,String beanName) { 再次获取了类中标注了@AutoWired、@Value、@Inject属性的信息 InjectionMetadata metadata = findAutowiringMetadata(beanName,bean.getClass(),pvs); 属性注入 metadata.inject(bean,beanName,pvs); } (BeanCreationException ex) { throw ex; } (Throwable ex) { throw new BeanCreationException(beanName,"Injection of autowired dependencies failed" pvs; }
在该方法中又一次获取了类中标注了@AutoWired、@Value、@Inject属性的信息,重点是下面这行代码,
属性注入
metadata.inject(bean,pvs);
下面看inject方法,
void inject(Object target,@Nullable String beanName,@Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = .checkedElements; 如果checkedElements为空,则取injectedElements Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : .injectedElements); elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } 进行属性注入 element.inject(target,pvs); } } }
上面在进行属性注入的时候调用了element.inject方法,该方法在InjectionMetadata.InjectedElement类中,进去该方法看到如下,
* Either this or {@link #getResourceToInject} needs to be overridden. */ protected inject(Object target,@Nullable String requestingBeanName,@Nullable PropertyValues pvs) Throwable { if (.isField) { Field field = (Field) .member; ReflectionUtils.makeAccessible(field); field.set(target,getResourceToInject(target,requestingBeanName)); } else { (checkPropertySkipping(pvs)) { ; } { Method method = (Method) .member; ReflectionUtils.makeAccessible(method); method.invoke(target,requestingBeanName)); } (InvocationTargetException ex) { ex.getTargetException(); } } }
看这方法的注释,意思是需要覆盖该方法,也就是说这里调用的不是上面的inject方法,在回到下面的代码
再来看AutowiredFieldElement是什么,
AutowiredFieldElement是AutowiredAnnotationBeanPostProcessor中的内部类,继承了InjectionMetadata.InjectedElement类,上面提到了该方法,那么该类中肯定覆盖了inject方法
@Override
void inject(Object bean,1)"> Throwable {
Field field = (Field) .member;
Object value;
.cached) {
value = resolvedCachedArgument(beanName,1)">.cachedFieldValue);
}
{
DependencyDescriptor desc = new DependencyDescriptor(field,1)">.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null,"No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
{
value = beanFactory.resolveDependency(desc,autowiredBeanNames,typeConverter);
}
(BeansException ex) {
new UnsatisfiedDependencyException( InjectionPoint(field),ex);
}
.cached) {
if (value != null || .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 = ShortcutDependencyDescriptor(
desc,autowiredBeanName,field.getType());
}
}
}
{
;
}
this.cached = ;
}
}
}
) {
ReflectionUtils.makeAccessible(field);
field.set(bean,value);
}
}
}
此方法的具体执行逻辑暂时不说。
三、使用场景
上面大体分析了AutowiredAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition和postProcessProperties两个方法,了解了其作用及执行时机,文中遗留的问题后面会继续分析。
有不当之处,欢迎指正,感谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。