@Autowired底层实现
admin
2024-01-16 16:37:56
0

@Autowired是一个用于注入容器的注解他是按照类型查找bean  NoSuchBeanDefinitionException如果么有相关类型;如果有两个相同类型的bean则按照名字查询bean如果按照名字也没有找到则会抛出NoUniqueBeanDefinitionException
 

@Autowired注解可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作

autowire属性,自动装配(按照类型装配,通过set方法,且方法可以省略)

注解实现注入主要是通过 bean 后置处理器 BeanPostProcessor 接口的实现类来生效的。BeanPostProcessor 后置处理器是在 spring 容器启动时,创建 bean 对象实例后,马上执行的,对 bean 对象实例进行加工处理。@Autowired 是通过 BeanPostProcessor 接口的实现类AutowiredAnnotationBeanPostProcessor 来实现对 bean 对象对其他 bean 对象的依赖注入的。

底层原理
在Spring源代码当中,Autowired注解位于包org.springframework.beans.factory.annotation之中

1.核心逻辑在buildAutowiringMetadata中
通过反射获取该类的每一个字段和方法,并且分别用 findAutowiredAnnotation方法遍历每一个字段和方法,如果有@Autowired注解修饰,则返回注解相关属性。最后这个方法返回的就是包含所有带有autowire注解修饰的一个InjectionMetadata集合。
 

private InjectionMetadata buildAutowiringMetadata(Class clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;} else {List elements = new ArrayList();Class targetClass = clazz;do {List currElements = new ArrayList();ReflectionUtils.doWithLocalFields(targetClass, (field) -> {MergedAnnotation ann = this.findAutowiredAnnotation(field);if (ann != null) {if (Modifier.isStatic(field.getModifiers())) {if (this.logger.isInfoEnabled()) {this.logger.info("Autowired annotation is not supported on static fields: " + field);}return;}boolean required = this.determineRequiredStatus(ann);currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));}});ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {MergedAnnotation ann = this.findAutowiredAnnotation(bridgedMethod);if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {if (Modifier.isStatic(method.getModifiers())) {if (this.logger.isInfoEnabled()) {this.logger.info("Autowired annotation is not supported on static methods: " + method);}return;}if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);}boolean required = this.determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));}}});elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();} while(targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);}}

2.InjectionMetadata类

这个类由两部分组成: targetClass目标类和我们要获得的injectedElements集合。

 public InjectionMetadata(Class targetClass, Collection elements) {this.targetClass = targetClass;this.injectedElements = elements;}

3.实现注入逻辑

 调用InjectionMetadata中的公共inject方法遍历调用protect的inject方法

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);return pvs;} catch (BeanCreationException var6) {throw var6;} catch (Throwable var7) {throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);}}

4.调用InjectionMetadata中的公共inject 

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Collection checkedElements = this.checkedElements;Collection elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;if (!((Collection)elementsToIterate).isEmpty()) {Iterator var6 = ((Collection)elementsToIterate).iterator();while(var6.hasNext()) {InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();element.inject(target, beanName, pvs);}}}

5.遍历调用protect的inject方法 

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, this.getResourceToInject(target, requestingBeanName));} else {if (this.checkPropertySkipping(pvs)) {return;}try {Method method = (Method)this.member;ReflectionUtils.makeAccessible(method);method.invoke(target, this.getResourceToInject(target, requestingBeanName));} catch (InvocationTargetException var5) {throw var5.getTargetException();}}}

相关内容

热门资讯

红杉中国200亿元并购意大利“... 意大利奢侈运动鞋制造商Golden Goose黄金鹅正式迎来全新资本格局,私募股权投资公司HongS...
A股收盘,近百股涨停,近百股跌... 【大河财立方消息】A股市场,“冰与火之歌”持续上演。 大河财立方记者梳理,6月25日,A股收盘,上证...
黄金“不灵了”,高端金饰的溢价... 古法黄金到底能不能走出脱离金价波动的独立溢价 作者:赵心怡 2026年开年,国际金价一路狂飙至近56...
朗迅科技由董事长徐振控制46%... 瑞财经 刘治颖 6月24日,杭州朗迅科技股份有限公司(以下简称:朗迅科技)深主板IPO获受理,保荐机...
两部门:2030年可再生能源制... 【两部门:2030年可再生能源制氢规模达到200万吨】财联社6月25日电,国家发展改革委、国家能源局...
原创 警... 大家好,这里是全球脉冲。 6月16日,日本央行宣布加息25个基点,政策利率上调至1%,创下31年来最...
黄金钻石回收怎么选?上海市场常... 近年来黄金价格持续走高,不少上海市民都有变现家中闲置黄金首饰、投资金条的打算。但市面上回收门店数量众...
专访火山引擎谭待:模型好对Ma... 文 | 邓咏仪 编辑 | 张雨忻 火山引擎总裁谭待 来源:火山引擎 过去三年,火山引擎总裁谭待给团...
女董事长深夜被带走,牵出金融旧... *此图由AI生成 作者| 史大郎&猫哥 来源| 是史大郎&大猫财经Pro 大半夜的,一家上市公司董事...
盯盯拍报考港交所上市:出海翻红... 撰稿|贝多 来源|贝多商业&贝多财经 6月22日,盯盯拍(深圳)技术股份有限公司(下称“盯盯拍”)递...
苏州千亿市值上市公司+1! A股“苏州板块”又诞生了一家千亿市值企业。 昨日(6月25日),苏州上市公司永鼎股份股价在昨日涨停的...
芯片股猛拉!600667,一字... 【导读】创业板指一度涨超2%,存储芯片、半导体、电子元器件等方向涨幅居前 中国基金报记者 李智 一起...
分析师:海峡收费与否已不重要 ... 来源:格隆汇APP 格隆汇6月25日|阿曼方面重申,霍尔木兹海峡未来安排不涉及通行费。美国财经网站i...
《内外贸一体化企业评价通则》团... 齐鲁晚报·齐鲁壹点记者 管悦 6月25日,《内外贸一体化企业评价通则》团体标准审查会在济南召开。该标...
提升AI智能体工作流的速度与能... 智能体工作流是一种由AI驱动的软件系统,它通过串联多个模型与外部工具来处理复杂任务,例如分析视频并回...
热搜!又有纸尿裤被曝检出甲酰胺... 来源:市场资讯 (来源:北京商报) 网友:“囤了200多包”。 近日,多个婴幼儿纸尿裤品牌“被检出...
埃森哲内部录音曝光:企业AI使... IT之家 6 月 26 日消息,科技媒体 404Media 昨日(6 月 25 日)发布博文,披露了...
FIBA期待杨瀚森表现 最新实... 北京时间6月25日消息,FIBA国际篮联公布了最新一期世界杯预选赛亚太区球队实力榜,中国男篮排在澳大...
收评:创业板指放量反弹涨2.8... 市场冲高回落后,再度震荡拉升。黄白线分化明显,权重股走势较强。量能明显放大,沪深两市成交额3.59万...