Java Spring源码运行原理
了解Spring源码
为什么?
1、企业的架构都是基于Java开发,而Java WEB开发中Spring基于大一片。
2、学习Spring是通过up主狂神的视频,但是发现他只是讲了应用而不讲相关原理。
3、感觉自己对Spring也不太了解,只是浅层的了解了相关的AOP和IOC容器
有什么用?
1、有益于了解Spring相关的漏洞
2、以后对学习开发WEB也有好处
3、进一步学习SpringBoot有帮助
BeanDefinitionReader和BeanDefinition
所有都是从这一条语句开始的。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
那么applicationContext是如何生成的呢?
我们每次在applicationContext.xml中定义的bean定义,比如如下
<bean id="UserDaoImpl" class="com.zpchcbd.dao.UserDaoImpl"></bean>
它是如何通过applicationContext.getBean方法来进行获取的?
这里新的知识点:BeanDefinitionReader和BeanDefinition
首先spring中提供了一个接口BeanDefinitionReader类,spring中实现该类的对象存在方法先对applicationContext.xml的定义Bean先进行读取,每个Bean都会生成一个BeanDefinition(Bean定义信息类)存储在Spring Container中去
接着spring就会通过对每个BeanDefinition对象中存储的信息进行对应的实例化操作(具体的操作就是通过反射)
小知识点:
实例化:在堆中默认开辟内存空间,此时实例化的对象的属性都是默认值
初始化:填充实例化对象的属性,此时实例化对象的属性不再是默认值
BeanFactory
此时已经来到了如下图的阶段
那么具体的实例化又是如何进行的呢?具体的操作是通过反射操作。
这里就要引出BeanFactory这个接口类了,这个类的作用 The root interface for accessing a Spring bean container.,只要是实现了该接口的类都可以对相关的bean来进行操作,比如实例化操作。
BeanFactory就提供了getBean的方法,具体的反射操作就是在getBean方法中进行的。
这里还顺便引出一个知识点BeanFactoryPostProcessor对象
BeanFactoryPostProcessor
其中的PostProcessor这个被大家称作为增强器/后置增强器。
在spring的BeanFactory实现类在对每个Bean进行实例化之前可能还会进行一个操作,就是关于扩展的操作。
这里需要举个例子来说明,在配置dataSource的时候,一般都会将单独的一个properties.property文件来进行引入,然后在dataSource中配置property的时候来通过来进行引入
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="jdbc:${dbname}"/> </bean>
其中对${xxx}进行替换的时候就是通过了spring中自带的工具类PlaceholderConfigurerSupport,而这个类就是一个来实现这个功能的,而这个PlaceholderConfigurerSupport类就是实现了BeanFactoryPostProcessor接口类。
此时到这里的话学习的spring的图就是如下
BeanPostProcessor
这个对象和BeanFactoryPostProcessor看起来很像,但是这个BeanFactoryPostProcessor对象是对bean实例化之前进行的增强。
而这里学习的BeanPostProcessor是对Bean对象所进行的操作,具体是什么如下所示,可以看到这个BeanPostProcessor有两个地方都操作了,一个是postProcessBeforeInitialization 还有一个是postProcessAfterInitialization,具体实现是通过AOP来进行实现的
上面讲到的其中有一部分就是关于Bean初始化的生命周期
其实就是 实例化Bean -> 填充属性 -> BeanPostProcessor:before -> init初始化属性 -> BeanPostProcessor:after
这里继续来讲下,这里又需要去了解下BeanFactory,该接口中有讲述到Bean的生命周期的运行过程
这里还可以跟图来进行对比下,如下图所示,可以看到后面的三个方法都是一一对应的
但是需要注意的是,这里只是Bean生命周期的初始化,并不是完整的生命周期,这里并没有涉及相关的Bean结束的生命周期相关操作。
Environment接口
Spring其中的一个StandardEnvironment对象对该接口进行了实现
它的作用就是:就是为了spring后续的使用更加的方便
ClassPathXmlApplicationContext执行流程
这里直接开始跟ClassPathXmlApplicationContext,在该当前打下断点进行跟踪
首先会先设置好要读取的xml文件的位置
再接着就是进入到refresh方法中
prepareRefresh(第一个)
reFresh方法先执行prepareRefresh方法
这个prepareRefresh方法就是对环境信息属性进行初始化操作,其中的getEnvironment().validateRequiredProperties方法同样说明了容器用到了相关的系统属性
obtainBeanFactory(第二个)
接着Spring框架实例化BeanFactory对象,因为只有有了BeanFactory对象,spring才可以对Bean相关的配置信息进行读取操作
跟到obtainBeanFactory方法中refreshBeanFactory的方法,就可以看到其中的BeanFactory的初始化操作
上面图中的loadBeanDefinitions方法就是通过生成的beanFactory对象来对相关的xml文件来进行读取相关的Bean标签,如下图所示
loadBeanDefinitions(第三个)
读完了xml配置文件并且生成了BeanFactory,那么此时就是开始通过xml文件中bean标签来生成对应的BeanDefinitions对象,loadBeanDefinitions调用完了之后,此时下面就可以看到相关的beanDefinitionMap中存储了xml中相关的BeanDefinition对象
prepareBeanFactory(第四个)
出来之后就是第三个方法prepareBeanFactory了,这个方法的话其实还是初始化刚才生成的BeanFactory对象的属性,如下图所示
postProcessBeanFactory(第五个)
再接着根据下面的图中的流程,那么此时就开始相关的增强类的操作了,这里继续来到第四个方法postProcessBeanFactory的调用,这个就是相关增强器的操作
但是该默认的postProcessBeanFactory该方法是一个空方法,需要让我们自定义去实现,这里就不深究,了解即可
再接着就是第五个方法invokeBeanFactoryPostProcessors,这个方法就是执行增强器的方法操作,可以看到注释中进行了解释“实例化并且调用所有已经注册好的BeanFactoryPostProcessor对象
也就是如下的地方的增强器的操作
registerBeanPostProcessors(第六个)
来到第六个方法registerBeanPostProcessors
这个方法也看到过,虽然跟增强器的名称非常相象,但是这个是作用于实例化Bean的期间操作的。
它会先将要执行的BeanPostProcessor先进行注册到BeanFactory中去(这里是跟到registerBeanPostProcessors中方法进行看到的,稍微了解即可)
initMessageSource(第七个)
initMessageSource方法,就是进行国际化处理,举个例子一个网站做了不同语言的转化处理,这种就相当于是国际化处理
initApplicationEventMulticaster(第八个)
开始进行初始化应用事件监听器多播器操作,为后面的registerListeners注册监听器做准备。
// Initialize event multicaster for this context.
onReFresh(第八个)
空实现
registerListeners(第八个)
注册监听器,上面的initApplicationEventMulticaster方法就是实例化了相关监听器,而这里的操作就是对这些监听器进行了注册操作
finishBeanFactoryInitialization(第九个)
重点开始了,来看下对这个方法的解释,可以看到下面的注释是说明要实例化所有非懒加载的单例对象
这里打断点然后进行跟踪,跟进该方法又会来到beanFactory.preInstantiateSingletons方法中,这个方法是核心,这里面就会进行初始化所有之前注册到beanFactory中的所beandefiniations的所有对象
也就是如下的如下部分
这里继续跟进去这里就开始获取之前注册到beanDefinitionNames的所有信息
再接着就是通过遍历该beanDefinitionNames来对每一个bean进行实例化操作,这里会先判断是否是isFactoryBean
这里简单的学习下factoryBean和beanFactory的区别,解释如下
在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似,自己感觉了解即可,也不是干开发的。
继续跟到getBean方法中,可以看到其中又进行了doGetBean的操作
这里继续跟入,一般自定义的bean标签(我这里说的自定义是自定义自己写的类,如果是spring自身提供的类可能走的就不是这里,就比如property-placeholder)
这里继续跟进createBean中,接着就会来到这里doCreateBean的方法,一个小知识点,在spring中一般前缀为"do"的,这种才是真正工作的方法
继续跟进doCreateBean方法中,这里的步骤就是获取当前要实例化bean的相关的构造方法,根据有无构造参数来进行判断通过哪个构造方法来进行实例化,我这里走的就是默认的构造方法,也就是无参构造方法
这里一直跟会走到如下的地方,也就是spring最终通过反射来进行实例化bean的操作来完成
这里继续回到doCreateBean方法中,接下来继续走,上面已经实例化了Bean对象,那么根据之前学习的流程图中,那儿此时就开始准备填充属性了,这里的populateBean方法就是进行填充属性的操作,主要我这里走的是默认的构造参数,并且也没实现相关的属性赋值,所以这里就没有填充属性的操作了
到这里,在doCreateBean中,具体第一个操作是对Bean类对象进行了实例化,第二个操作就是对该实例化属性进行了属性填充,最后返回该实例化的Bean对象
继续走进下面的initializeBean方法,那么根据老师讲的流程图,此时就应该是执行 BeanPostProcessor:before 和 初始化执行bean的init方法 和 BeanPostProcessor:after,这里往下跟来进行观察。
这里的invokeAwareMethods需要了解下,在BeanFactory中有讲述到,这个方法执行的是在BeanPostProcessors之前的操作,也就是下面红框中的操作
最后就是BeanPostProcessor:before 和 初始化执行bean的init方法 和 BeanPostProcessor:after的操作了,也就是如下图所示
最后上面的Bean操作都执行完了,最后返回该对应的Bean的实例化以及初始化之后的对象,到这里一个Bean的生成的生命周期就到这里结束了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!