@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();}}}

相关内容

热门资讯

原创 4... 写在文章前的声明:在本文之前的说明:本文中所列的投资信息,只是一个对基金资产净值进行排行的客观描述,...
胜宏科技港股大涨49% 做完英... 记者 陈月芹 4月21日,全球AI算力板龙头胜宏科技(02476.HK)登陆港交所,上市首日股价大涨...
永赢基金:聚焦“科技新锐”,科... 数据来源:Wind,时间统计区间为2025/1/1-2026/4/21,指数过往表现不预示未来,不构...
五大阅读趋势显现!当当网发布2... 在第31个世界读书日即将来临之际及首个全民阅读活动周期间,当当网正式发布2026国民阅读洞察报告。 ...
业绩逐季回暖 老百姓大药房一季... 上证报中国证券网讯(记者 夏子航)4月22日晚,老百姓大药房发布2025年年报和2026年一季报。今...
中国20强城市大洗牌:苏州接近... 中国的城市经济竞争格局一直在变化,每年发布的GDP数据都会对城市经济实力进行重新排列。2025年榜又...
直击金宏气体股东会:预期年内氦... 《科创板日报》4月22日讯(记者 郭辉)金宏气体日前举行2025年度股东大会。会上该公司审议了公司年...
5月1日起,俄据悉将叫停哈萨克... 据行业消息人士透露,俄罗斯将于5月1日起停止经友谊管道转运哈萨克斯坦输往德国的石油,相关调整计划已送...
深化具身智能生态布局 京东携手... 4 月 22 日,京东与国内消费级人形机器人头部企业松延动力正式达成三年期战略合作。双方将围绕产品研...
原创 帮... 先问你一个问题,美伊停火今晚到期,按常理避险情绪该升温,黄金应该涨吧?结果恰恰相反——原油涨了,黄金...
300295、600889,将... 三六五网、南京化纤,将被*ST。 公司股票自4月23日开市起停牌一天,于4月24日开市起复牌并实施退...
能源大变天!外媒:羡慕中国的石... 这一次油价突破 110 美元的能源危机,着实魔幻。如果放在十年前,没人会相信中国能在这场风波中获利,...
黄金涨跌两难,现在还能上车吗? 中新网4月22日电(记者 左雨晴) 四月以来,美伊局势反复拉扯,美联储降息预期一变再变。黄金价格在4...
“我身体健康”,库克现身员工大... 当地时间4月21日,受苹果官宣CEO换届影响,公司股价盘中下探超2%,总市值失守4万亿美元关口,收盘...
库克留下一个悬念 工程师能否拯救创新节奏? 听筒Tech(ID:tingtongtech)原创 文 | 赵 森 ...
探索消费信贷与社交支付深度融合... 腾讯这一金融产品再添新功能,4月19日,北京商报记者注意到,微信分付灰度测试转账功能引发热议,在向微...
土耳其主要银行股指早盘下跌2% 每经AI快讯,4月20日,土耳其主要银行股指早盘下跌2%。 每日经济新闻
好用的OTA代运营源头厂家 在如今竞争激烈的酒旅行业中,OTA代运营服务成为了众多酒店、民宿提升竞争力的关键。但市场上的代运营厂...
成都五一出游全国热门第三 “五一”假期临近,同程旅行最新发布的《2026“五一”旅行趋势报告》显示,今年“五一”期间成都同时位...