进入到上面的applyMergedBeanDefinitionPostProcessors
方法里:
1 | java复制代码protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { |
其中实现了postProcessMergedBeanDefinition方法的一个实现类MergedBeanDefinitionPostProcessor
是要分析的重点
构造方法:
1 | java复制代码public AutowiredAnnotationBeanPostProcessor() { |
把Autowired和Value标签加入到类型为Set的autowiredAnnotationTypes里。
当BeanName是自定义的WelcomeController时,从applyMergedBeanDefinitionPostProcessors方法的postProcessMergedBeanDefinition处进入断点:
1 | java复制代码@Override |
findAutowiringMetadata是寻找被注解的元数据:
1 | java复制代码private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { |
该方法扫描到类里的属性或者方法有对应的注解,就会将其封装起来,最终封装成InjectionMetadata实例返回,进入到InjectionMetadata里:
其中包含了哪些需要注入的元素,以及元素要注入到哪个目标类中,targetClass
代表目标bean的class对象,injectedElements
保存的是需要被注入的元素,即被Autowired或Value注解的属性或方法,checkedElements
里面只保存了由Spring默认处理的属性、方法。
injectedElements集合的泛型是InjectedElement,保存单个InjectedElement的值member
用于保存被Autowired、Value注解标记的属性,isField
用来决定member是Field还是方法,PropertyDescriptor
可以对属性反射读写操作
回到findAutowiringMetadata方法,cacheKey是metadata在容器缓存中的名字,获取到了之后会先在容器缓存里查一下先前有没有获取到InjectionMetadata
对象,之后会执行needsRefresh
方法
1 | java复制代码public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) { |
该方法判断是否需要重新去扫描获取bean,如果不需要就会直接从缓存里返回先前注册的metadata实例。
在 if 里用到了双重锁检查机制,最终会调用
1 | java复制代码metadata = buildAutowiringMetadata(clazz); |
创建出metadata来,进入到buildResourceMetadata:
1 | java复制代码private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { |
首先看一下该类是否有资格成为被Autowired或Value标记的候选类,主要是看一下class对象是不是普通的class,即这两个注解在这个class里有没有表示别的意思,判断逻辑如下:
1 | java复制代码public static boolean isCandidateClass(Class<?> clazz, String annotationName) { |
注解有java开头的注解就算是候选者;如果clazz是以java.打头或是Order类型的,则标签不会起作用,不能算做候选者
回到AutowiredAnnotationBeanPostProcessor.java的buildAutowiringMetadata
方法
之后会通过循环来遍历class里面的属性元素以及方法元素,不管是何种元素都会执行findAutowiredAnnotation
方法收集被Aotowired或Value标记的Field
进入到findAutowiredAnnotation
方法里:
1 | java复制代码@Nullable |
isPresent方法判断是否被两种标签修饰,是的话将标记信息返回
回到buildAutowiringMetadata,
之后判断Field是否是静态的,是的话会抛异常,因为静态Field不支持注入
之后再会获得Autowired里面的require属性
1 | java复制代码boolean required = determineRequiredStatus(ann); |
获取到相关信息之后就会将field和required属性添加到list里面
1 | java复制代码currElements.add(new AutowiredFieldElement(field, required)); |
之后就会把收集到的被注解标记的属性以及方法实例,存储到集合中
最后返回:
1 | java复制代码return InjectionMetadata.forElements(elements, clazz); |
进入到forElements方法里:
1 | java复制代码public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) { |
该方法会将收集到的被标记的元素放入到新创建的InjectionMetadata实例里
回到findAutowiringMetadata,
最后将metadata存储到缓存里
回到postProcessMergedBeanDefinition方法
1 | java复制代码@Override |
在获取到了metadata之后,会调用checkConfigMembers方法,进入到方法里:
1 | java复制代码public void checkConfigMembers(RootBeanDefinition beanDefinition) { |
会把需要spring容器用默认策略注入的injectedelements集合给保存到前面说的checkedElements里,这样就完成了收集被Autowired和Value标记的属性和方法,有了实例之后就能通过调用其inject方法在合适的时候进行属性值的注入
回到doCreateBean
本文转载自: 掘金