java spring运行原理

了解Spring源码

为什么?

1、企业的架构都是基于Java开发,而JavaWEB开发中Spirng基于大一片。

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的生成的生命周期就到这里结束了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值