依赖注入
2022-10-14 09:13:16 0 举报
Spring的@Autowired和@Resource注解注入详解
作者其他创作
大纲/内容
GenericTypeAwareAutowireCandidateResolver#isAutowireCandidate
DefaultListableBeanFactory#determineAutowireCandidate
QualifierAnnotationAutowireCandidateResolver.getSuggestedValue
指定了名字
获得instanceCandidate
DefaultListableBeanFactory#doResolveDependency
不存在
判断类型
6
否
CommonAnnotationBeanPostProcessor#autowireResource
font color=\"#f44336\
如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配
extends
this.lazyLookup
将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该Bean时,就可以直接拿缓存的结果对象beanName去BeanFactory中去那bean对象了,不用再次进行查找了
DefaultListableBeanFactory#resolveMultipleBeans
则只会根据name或注入点的名字(属性名字或者方法参数名字)去找bean
有@Lazy注解
Map
匹配descriptor的名字,要么是字段的名字,要么是set方法入参的名字
将字段信息构造成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中
SimpleAutowireCandidateResolver#isAutowireCandidate#检查BeanDefinition的isAutowireCandidate属性,为true则表示通过筛选
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition//寻找注入点
返回
AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject方法注入
调用Map的values()方法返回去
寻找注入点
获取@Autowired中的required属性的值
Optional.class
最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并缓存。
AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor#resolveShortcut
DefaultListableBeanFactory#resolveDependency
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject字段注入
此处就进行实例化,调用getBean
DefaultListableBeanFactory#doGetBeanNamesForType
存在
beanFactory.resolveDependency()
4
经过上述验证之后,当前beanName才能成为一个可注入的,添加到result中
AutowireCapableBeanFactory#resolveBeanByName
构建对象注入点
将对应的字段封装为DependencyDescriptor对象
autowiredAnnotationTypes
factory.containsBean(name)
@Resource注解注入方式
对象包装成Optional返回去
没有指定
3
直接生成一个ObjectFactory对象
this.lazyLookup = (lazy != null && lazy.value());
注入点进行注入
injectionMetadataCache
放入缓存
取优先级最高的Bean;判断@Priority值,取值最小的。如果两者相同就报错
descriptor.getDependencyType()
put
get
5
获取@Value所指定的值
直接匹配
返回对象
@Autowired方式的注入
判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断
ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary
beanDefinitionNames
false字段
typeToMatch.isInstance(beanInstance)
如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
determineAutowireCandidate()多个Bean筛选出一个返回去
没有
寻找注入对象,返回去对象
则和@Autowired一样,先byType再byName
1
在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
@Resource注解是否使用了名字
this.isDefaultName = !StringUtils.hasLength(resourceName);
CommonAnnotationBeanPostProcessor#buildLazyResourceProxy#构建代理对象
调用BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象
AutowiredAnnotationBeanPostProcessor#postProcessProperties入口
获取并解析Value上得值并返回
遍历当前类的所有的属性字段Field
先判断有没有解析
CommonAnnotationBeanPostProcessor#postProcessProperties#解析注入点
使用@Resource时没有指定具体的name,那么则用field的name,或setXxx()中的xxx
DefaultListableBeanFactory#determineHighestPriorityCandidate
返回对象instanceCandidate
直接返回Map
result.add(beanName);
instanceCandidate instanceof Class
Collection
根据LookupElement从BeanFactory找到适合的bean对象
查看字段上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该字段是一个注入点
找出BeanFactory中类型为type的所有的Bean的名字
ObjectFactory.classObjectProvider.class
doResolveDependency(descriptorToUse)
CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
beanFactory.resolveDependency
this.cached
将MethodParameter对象封装为DependencyDescriptor对象
有可能筛选出来的是某个bean的类型
InjectionMetadata#inject#遍历每个注入点进行注入
根据类型去找BeanName
拿出类上注解
static filed不是注入点,不会进行自动注入
遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
判断descriptor的类型
返回resolvedBeanNames
descriptor.getDependencyName()
DefaultListableBeanFactory#findAutowireCandidates
resolvableDependencies中key为type的对象找出来并添加到result中
对于原型Bean(多例bean),第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
遍历字段和方法寻找注解@Resource
this.cached = true;
QualifierAnnotationAutowireCandidateResolver#isAutowireCandidateQualifierAnnotationAutowireCandidateResolver#checkQualifiers
解析注入点
利用反射将结果对象赋值给字段
如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
CommonAnnotationBeanPostProcessor#getResource
遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
InjectionMetadata#inject
trueShortcutDependencyDescriptor直接去找ben
size >1
判断Bean工厂是否存在该注入点的名字
去beanDefinitionMap中匹配
遍历根据type找出的beanName,判断当前beanName对应的Bean是不是能够被自动注入
在调用getObject()方法时调用
findAutowiringMetadata
接着遍历方法最后方法信息构造成一个AutowiredMethodElement对象
先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断
2
CommonAnnotationBeanPostProcessor#buildResourceMetadata
false方法
利用反射将找到的所有结果对象传给当前方法,并执行。
new ResourceElement()
遍历每个注入点
执行代理对象时,调用getTarget()方法
//寻找注入点AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinitionAutowiredAnnotationBeanPostProcessor#findAutowiringMetadataAutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata#匹配注解AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation
是
DefaultListableBeanFactory#determinePrimaryCandidate
0 条评论
回复 删除
下一页