当前位置: 首页 > ai >正文

@Autowired注入底层原理

       常见的@Autowired有以下5种形式进行注入,下面模拟了Spring中对这5种形式的注入进行解析并写入Spring容器内。

     1.根据成员变量的类型获取

     2.根据方法中参数类型进行获取

     3.结果包装为Optional<bean2>类型

     4.结果包装为ObjectProvider

     5.对@lazy进行处理

package com.example.springdemo.demos.a15;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Optional;
@Configuration
public class TestAutowired {public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestAutowired.class);DefaultListableBeanFactory factory = context.getDefaultListableBeanFactory();//1.根据成员变量的类型获取DependencyDescriptor descriptor = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);System.out.println(factory.resolveDependency(descriptor, "bean1", null, null));//2.根据参数类型进行获取Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);DependencyDescriptor descriptor2 = new DependencyDescriptor(new MethodParameter(setBean2, 0),false);System.out.println(factory.doResolveDependency(descriptor2, "bean1", null, null));//3.结果包装为Optional<bean2>类型DependencyDescriptor dd3 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean3"),false);if(dd3.getDependencyType() == Optional.class){dd3.increaseNestingLevel();Object result = factory.doResolveDependency(dd3,"bean1",null,null);System.out.println(Optional.ofNullable(result));}//4.结果包装为ObjectProviderDependencyDescriptor dd4 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean4"),false);if(dd4.getDependencyType() == ObjectFactory.class){dd4.increaseNestingLevel();ObjectFactory objectFactory = new ObjectFactory() {@Overridepublic Object getObject() throws BeansException {Object result = factory.doResolveDependency(dd4,"bena1",null,null);return result;}};System.out.println(objectFactory.getObject());}//5.对@lazy进行处理DependencyDescriptor dd5 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean5"),false);ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();resolver.setBeanFactory(factory);Object proxy = resolver.getLazyResolutionProxyIfNecessary(dd5, "bean1");System.out.println(proxy.getClass());}@Componentstatic class Bean1 {@Autowiredprivate Bean2 bean2;@Autowiredpublic void setBean2(Bean2 bean2){this.bean2 = bean2;}@Autowiredprivate Optional<Bean2> bean3;@Autowiredprivate ObjectFactory<Bean2> bean4;@Autowired @Lazyprivate Bean3 bean5;}@Component("bean2")static class Bean2 {private String name;}@Component("bean3")static class Bean3 {private String name;}
}

第一种方式:

         通过成员变量的类型获取并注入@Autowired底层。DependencyDescriptor descriptor = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);Spring底层通过这个类进行依赖解析,后面都用到了这种方式。

第二种方式:

        通过根据方法里面的参数类型进行获取。

第三种方式:

       获取包装类里面的bean2,首先拿到Optional<bean2>,后面dd3.increaseNestingLevel()增加了嵌套层级,使得可以进一步对Optional<bean2>里面的bean2进行解析。

第四种方式:

       注入的对象是 ObjectFactory<Bean2> bean4的形式。通过下面的方式获取到ObjectFactory工厂对象里面的Bean2对象。可以延迟加载Bean2,等真正需要的时候才去获取。

 ObjectFactory objectFactory = new ObjectFactory() {@Overridepublic Object getObject() throws BeansException {Object result = factory.doResolveDependency(dd4,"bena1",null,null);return result;}};

第五种方式:

      配合使用了@Lazy的成员变量,通过ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver()解析@Lazy,获得代理对象。

测试结果:

       可以看到以上方式都正常解析并注入到Spring容器中了。

http://www.xdnf.cn/news/19475.html

相关文章:

  • STM32-FreeRTOS操作系统-任务创建
  • 洛谷 P5836 [USACO19DEC] Milk Visits S-普及/提高-
  • 贪心算法解决钱币找零问题(二)
  • 基于单片机倒车雷达/超声波测距设计
  • Linux->网络入门
  • 《论文阅读》从心到词:通过综合比喻语言和语义上下文信号产生同理心反应 2025 ACL findings
  • infinityfree mysql 加入数据库部分 filezilla 设备共享图片和文本不用浏览器缓存
  • 第六章 Vue3 + Three.js 实现高质量全景图查看器:从基础到优化
  • hive表不显示列注释column comment的问题解决
  • Linux signal 图文详解(二)信号发送
  • 为什么服务器接收 URL 参数时会接收到解码后的参数
  • DHT11-温湿度传感器
  • openEuler2403部署Redis8集群
  • 京东入局外卖,还有很多问题。
  • Ubuntu 服务器实战:Docker 部署 Nextcloud+ZeroTier,打造可远程访问的个人云
  • 学习 Android (十八) 学习 OpenCV (三)
  • OpenHarmony 分布式感知中枢深度拆解:MSDP 框架从 0 到 1 的实战指南
  • 餐饮外卖同城配送酒水寄存餐品加价换购促销小程序APP
  • Windows 安装配置解压版MongoDb
  • TFT屏幕:STM32硬件SPI+DMA+队列自动传输
  • 【RelayMQ】基于 Java 实现轻量级消息队列(五)
  • 2025 最新Vue前端面试题目 (9月最新)
  • AI 重构医疗诊断:影像识别准确率突破 98%,基层医院如何借技术缩小诊疗差距?
  • 设备服务管理上报方案
  • 两轮车车机 OS 演进路线深度解析
  • libmodbus源码分析
  • 【前端】《手把手带你入门前端》前端的一整套从开发到打包流程, 这篇文章都会教会你;什么是vue,Ajax,Nginx,前端三大件?
  • 差角函数差角矩阵位置编码
  • 无需服务器也能建网站:Docsify+cpolar让技术文档分享像写笔记一样简单
  • 手机版碰一碰发视频源码搭建,技术实现与实操指南