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

相关内容

热门资讯

2026别盼房价崩盘了!楼市分... 家人们,2026年开年就有个房产大V的言论炸了锅!说什么“房价跌了不用慌,家比房子值钱”,劝大家别再...
深圳龙岗:筑牢寄递防毒线,赋能... 为应对寄递渠道涉毒风险,提升一线从业者主动防御能力,一场别开生面的“筑牢寄递防毒线”沉浸式禁毒培训,...
20万颗卫星引爆A股,泼天富贵... 上周末最大的新闻,那还是属于航天。 倒不是谁又发火箭了,而是:中国一口气申请了超20万颗卫星! 如果...
恶意退货、“买真退假” 网购乱... 网购是如今很多人买衣服的主要方式,很多平台上也都有“七天无理由退货”的规则,让消费者可以放心买、放心...
解码基金“擒牛术”:布局十倍股... 证券时报基金研究院 匡继雄 刚刚过去的2025年,主动权益基金赛道跑出“现象级”赢家:永赢基金任桀管...
国家发改委原副主任扶持公司上市... 由中央纪委国家监委宣传部与中央广播电视总台央视联合摄制的电视专题片《一步不停歇 半步不退让》,于1月...
A股头条:商业航天又迎利好!中... 资讯速递 1、中国对日稀土出口许可审查被暂停?外交部回应 外交部发言人毛宁1月12日主持例行记者会。...
盘前必读丨中概股爆发金龙指数大... 【财经日历】 美国2025年12月CPI 2026三亚.国际种业科学家大会暨国际种业科技博览会(1/...
豪威集团“A+H”上市总市值1... 来源:长江商报 长江商报消息 ●长江商报记者 沈右荣 “芯片富豪”虞仁荣斩获了第三个IPO。 1月...
马斯克炮轰苹果谷歌联手打磨Si... IT之家 1 月 13 日消息,埃隆・马斯克(Elon Musk)今天(1 月 13 日)在 X 平...
原创 卖... 我朋友前年在城市边缘的新区买了个32层高层,是时下最流行的设计,精装修,会所配套一应俱全,那时候他还...
黄金站上4600美元再创新高,... 1月12日亚洲早盘,COMEX黄金期货价格直线拉升,站上每盎司4600美元,时隔两周再度刷新历史新高...
顺灏股份:投资轨道辰光事项对公... 人民财讯1月12日电,顺灏股份(002565)1月12日发布股票交易严重异常波动的公告,公司关注到近...
治疗白癜风无秘密?关键在“耐心... 在白癜风的治疗过程中,不少患者急于看到效果,四处寻求所谓的“治疗秘密”或“捷径”。但从临床诊疗经验来...
突发!商业航天牛股,停牌核查 1月12日晚,*ST铖昌公告称,公司股票交易连续10个交易日内4次出现同向股票交易异常波动情形,属于...
原创 女... 在探讨女性情感经历的复杂性时,我们不得不提到一个经常被提及的话题——恋爱次数。这不仅是一个关于个人成...
原创 对... 少年时阅读历史时,我们常常为项羽的失败感到困惑。他这位勇敢直接的青年,怎么会败给刘邦那个看似不怎么样...
英伟达与礼来共投10亿美元 建... 财联社1月13日讯(编辑 牛占林)英伟达与美国制药巨头礼来当地时间周一宣布,双方将在未来五年内投入1...
2026年做什么行业赚钱有前景... 站在2026年这个时间节点上,很多人明显感觉到,钱变得“聪明”了,也变得更难赚了。 过去那种靠信息差...
10亿基金落地 背靠广州工控庞... 观点网 近日,广州工控图南创业投资基金顺利完成备案,正式进入实质性运营阶段。 该基金由工控科创集团发...