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

@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.dtcms.com/a/361486.html

相关文章:

  • 吴恩达机器学习补充:决策树和随机森林
  • AUTOSAR AP R24-11 Log and Trace 文档总结
  • 贪心算法解决钱币找零问题(二)
  • CentOS10安装RabbitMQ
  • [特殊字符]【C语言】超全C语言字符串处理函数指南:从原理到实战
  • ARM的编程模型
  • TikTok Shop 物流拖后腿?海外仓系统破解物流困局
  • nginx是什么?
  • MQ使用场景分析
  • OpenHarmony 分布式感知中枢深度拆解:MSDP 框架从 0 到 1 的实战指南
  • 2025年- H104-Lc212--455.分发饼干(贪心)--Java版
  • 电动自行车淋水安全测试的关键利器:整车淋水性能测试装置的技术分析
  • 零基础深度学习技术学习指南:从入门到实践的完整路径
  • 大语言模型对齐
  • 中宇联SASE解决方案荣获最佳实践奖,助力国际零售企业数字化转型
  • 像信号处理一样理解中断:STM32与RK3399中断机制对比及 Linux 驱动开发实战
  • Kali自带的录屏工具:recordmydesktop
  • 响应式编程框架Reactor【8】
  • LINUX 91 SHELL:删除空文件夹 计数
  • 【C++】内存管理机制:从new到delete全解析
  • 如何对嵌入式软件进行单元测试
  • 增强现实—Gated-attention architectures for task-oriented language grounding
  • 8K4K图像评估平台
  • Shader开发(十九)统一变量纹理亮度调节
  • 永磁同步电机无速度算法--高频脉振方波注入法(新型位置跟踪策略)
  • Linux常用命令行大全:14个核心指令详解+实战案例
  • 第8篇c++Expression: (L“Buffer is too small“ 0
  • LintCode第401题-排序矩阵中的从小到大第k个数
  • ESP32驱动数字麦克风INMP441
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘tox’问题