Spring 源码浅析

环境搭建:

当前系统环境 JDK 1.8 IntelliJ 2020.3 gradle 6.8.3

官网down spring framework github.com/spring-proje

版本号 5.3.1

导入idea 新建module 进行简单测试,追踪运行过程。

编写Junit 测试类,run ,未得到运行结果。debug运行发现根本未进入test 方法。

定位问题:因为是直接未进入程序,在确认添加test 注解的情况下,那么肯定是不是代码编写问题,猜测是编译执行的问题。

File -> setting-> build -> build Tools -> gradle -> 发现两个配置:默认是Gradle,修改为IntelliJ IDEA

重新运行,发现编译异常:

java: 程序包jdk.jfr不存在

这个需要升级JDK 版本到11 ,并且保证compiler 里面 javac 的设置与project 中jdk 版本都是11,继续运行,又出现异常:

Kotlin: Calls to static methods in Java interfaces are prohibited in JVM target 1.6. Recompile with '-jvm-target 1.8'
这个看是需要将kotlin 编译的 jvm-tartget 版本从1.6改到1.8,去修改project依赖的module 中的版本,1.6的都改到1.8
重新运行,终于成功。

Spring 启动整体流程
预处理
prepareRefresh();

获取工厂bean
obtainFreshBeanFactory();

预处理工厂bean 完成一些初始化操作
prepareBeanFactory(beanFactory)

beanFactory后置处理⼯作

BeanFactory 初始化

实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
invokeBeanFactoryPostProcessors(beanFactory)

注册BeanPostProcessor(bean 初始化前后执行对应的方法)
registerBeanPostProcessors(beanFactory)

初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource()

初始化事件派发器
initApplicationEventMulticaster()

⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
onRefresh()

注册应⽤的监听器。实现了ApplicationListener接⼝的监听器bean
registerListeners()

初始化所有剩下的⾮懒加载的单例bean
finishBeanFactoryInitialization(beanFactory)

完成context的刷新,调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件 (ContextRefreshedEvent)
finishRefresh()

工厂bean 初始化

到底11步整个BeanFacoty 的初始化工作已经结束。最后第12步 衔接初始化Bean的主要内容

Bean 初始化

单独Bean 的初始化流程。

如果在第12步 populateBean 中发现有需要依赖的其他Bean ,那么继续创建依赖的Bean.一直向下创建,直至需要的bean 创建完成返回给自己完成初始化。

循环依赖问题

单例 bean 构造器参数循环依赖(⽆法解决)
prototype 原型 bean循环依赖(⽆法解决)

Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置
1.Spring解决循环依赖其实是通过提前暴露⼀个ObjectFactory对象来完成的,简单来说ClassA在调⽤构造器完成对象初始化之后,在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。

2.ClassA调⽤setClassB⽅法, Spring⾸先尝试从容器中获取ClassB,此时ClassB不存在Spring容器中。

3.Spring容器初始化ClassB,同时也会将ClassB提前暴露到Spring容器中

4.ClassB调⽤setClassA⽅法, Spring从容器中获取ClassA ,因为第⼀步中已经提前暴露了ClassA,因此可以获取到ClassA实例,完成ClassB的属性赋值

5.ClassA通过spring容器获取到ClassB,完成了对象初始化操作

Spring AOP

Spring 实现AOP思想使⽤的是动态代理技术

默认情况下, Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现任何接⼝时, Spring会选择CGLIB。当被代理对象实现了接⼝, Spring会选择JDK官⽅的代理技术。可以通过配置的⽅式,让Spring强制使⽤CGLIB

Spring 声明式事务

事务的传播⾏为

PROPAGATION_REQUIRED

如果当前没有事务,就新建⼀个事务,如果已经存在⼀个事务中,
加⼊到这个事务中

PROPAGATION_SUPPORTS

⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏

PROPAGATION_MANDATORY

使⽤当前的事务,如果当前没有事务,就抛出异常

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起

PROPAGATION_NOT_SUPPORTED

以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起

PROPAGATION_NEVER

以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则
执⾏与PROPAGATION_REQUIRED类似的操作

如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则
执⾏与PROPAGATION_REQUIRED类似的操作

声明式事务是 springAOP 思想的⼀种应⽤

@EnableTransactionManagment
通过@import引⼊了TransactionManagementConfigurationSelector类
selectImports⽅法导⼊了另外两个类:
AutoProxyRegistrar
registerBeanDefinitions() AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)
引⼊InfrastructureAdvisorAutoProxyCreator
继承了AbstractAutoProxyCreator,是⼀个后置处理器类

ProxyTransactionManagementConfiguration
@Configuration--注解配置类
主要完成了两个注册bean

AnnotationTransactionAttributeSource 属性解析器,
使⽤SpringTransactionAnnotationParser完成事务规则的解析

TransactionInterceptor 事务拦截器,继承自TransactionInterceptor,
在产生代理对象之前,与aop增强合并叠加。

发布于 2021-08-05 15:34