Spring源码分析之IOC的三种常见用法及源码实现(一)
1.ioc核心功能bean的配置与获取api
有以下四种
(来自精通spring4.x的p175)
常用的是前三种
第一种方式
第二种方式
定义
获取
第三种方式
定义
注意: 通过@Bean的形式是使用的话, bean的默认名称是方法名,若@Bean(value="bean的名称")那么bean的名称是指定的
去容器中读取Bean的信息(传入配置类)
获取
2.如何实现的
1.基于Java类配置的实现方式源码分析
1.就执行了这两句代码
先看看,打开构造器源码:
2.首先不急,主角儿AnnotationConfigApplicationContext 它有父类,因为类初始化顺序的关系,会先初始化父类,所以得看父类,一直看到最后父类为DefaultResourceLoader
DefaultResourceLoader,很明显是用来加载资源的,倒数第二个AbstractApplicationContext的无参构造中也是初始化一个加载资源相关:
Ok,再来看最后一个父类GenericApplicationContext了,父类默认初始化使用下面这个无参的
这里是创建了springioc体系中的一个重要的类DefaultListableBeanFactory,DefaultListableBeanFactory非常关键里面实现了ioc相关很多功能,可以提供给我们的AnnotationConfigApplicationContext使用(后面会看到)
3.ok父类都看完了,那就回到我们的主角儿AnnotationConfigApplicationContext了
我们来看它的构造器刚刚是什么代码(回归本身):
就两行。
4.先看第一句this.reader = new AnnotatedBeanDefinitionReader(this);
进去
它再次调用自己的构造器
这里还涉及了一个方法getOrCreateEnvironment(registry)
很明显这个方法从名字看就知道是有缓存的意思,获取或创建,如果是第一次则创建 第二次则就是获取了,第二次拿的第一次缓存的。如下:
ok,继续看,刚刚是从构造器到另一个构造器了:
ConditionEvaluator是计算conditon的解析器(后面会讲),这里很明显主要逻辑在 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
接下来AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);是重中之重,终于开始有大段逻辑了!之前都是各种继承跳转!
registerAnnotationConfigProcessors源码实现如下

挺长,先看第一部分:
很明显这是从registry里拿DefaultListableBeanFactory ,还记得前面讲主角儿AnnotationConfigApplicationContext的父类GenericApplicationContext吗?在它的无参构造中就创建了DefaultListableBeanFactory。现在到这个registry里去拿,而这个registry就是前面用this传过来的主角儿AnnotationConfigApplicationContext自然就有DefaultListableBeanFactory了。后面的逻辑就是null判断和设置比较器和解析器到里面了。

创建了一个set集合保存BeanDefinitionHolder(BeanDefinition是)。后面就非常多的if判断。这都是判断啥呢?
判断registry中是否存在一个个的常量定义的东西。那这些常量是什么呢?打开一看:
是个类的全路径,如果registry里面没有就执行最后一句(前两句都是给最后一句服务的):
也就是判断有没有这个类,没有就添加这个类进去,这这个类是用来解析配置注解的处理器。
还有个 public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
综合所见,这段代码后半部分其实就是注册spring支持的各种注解的解析器的逻辑
这个对应是用来解析自动装配注解的
最后如下:
好,以上这部分分析结束,回到主角儿AnnotationConfigApplicationContext,之前我们是从它的构造器:
中分析的第一句终于把这个reader完毕了,接下来分析第二句咯。
名字可以看出是类路径下的扫描器,开始查看源码!
继续跟进
第一个registry 还是之前说的DefaultListableBeanFactory传的this,第二个也就是 传了个true,是否使用默认的filter,选择了是。第三个之前讲过了,有则用没有则创建,缓存。继续跟
这部分代码前面就是赋值、注册默认的filters、设置从registry拿的环境设置、最后设置ResourceLoader
一部分一部分的看,先看registerDefaultFilters();
方法注释可以看到 意思是,注册这些默认的filter,@Component、@Repository、@Controller才会起作用
然后方法内部就注入添加Component.class进去了,让@Component起作用,而@Repository、@Controller本身都被打了@Component 是子注解,所以也连带起作用
后面部分就是判断jsr250 330相关注解了
到此看完了,回到上层上层去,至此
中的第二句我们也大致看完了,至此一个构造器看完了。大功告成.......了,一半。。。发现这个构造器是无参的,而我们之前用的两句代码:
中主角AnnotationConfigApplicationContext用的带class的构造器啊,看来没完,原来这个构造器还有上层调用,在这:
这里才是最开始那两行代码的第一次调用处。我们把this();看完了!
接下来看第二句register(annotatedClasses);,不断跟进
不断跟进到这
原来这句代码是把传入的配置类里的bean全给注册了。至此第二句完毕。至于最后第三句核心,留给下篇文章。一起加油!
__EOF__

本文链接:https://www.cnblogs.com/chz-blogs/p/11694405.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2017-10-17 子网掩码!如何划分子网掩码,计算IP地址
2017-10-17 计算机网络知识点总结2:IP协议(IPV4)