spring源码学习流程图
2021-07-22 17:07:12 1 举报
spring5.1源码解读流程图。包含,AOP,容器启动,spring配置类扫描,事务,自动注入等
作者其他创作
大纲/内容
创建事务后执行业务方法
1.3.2版本
触发同步器的beforeCompletion()
@Resource注解是否配置了name属性
@Resource注解注入过程
判断传播机制
返回对象包装成Optional
属性
获取Advisor中对应的Advice,并封装为MethodInterceptor
determineCandidateConstructors()方法执行流程
获取不到bean会报错
添加一个bean的后置处理器ApplicationListenerDetector
调用refresh()方法
直接返回Map
AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
设置扫描出来的接口为beanDefinition的ConstructorArgumentValues的属性设置BeanDefinition的beanClass为MapperFactoryBean,
Spring整合Mybatis
@Configuration的普通AOP不同点,@Configuration对应的BeanDefinition的BeanClass设置的enhancedClass而AOP对应的BeanDefinition的BeanClass还是原来的class所以配置类执行的所有方法都会经过代理逻辑,而普通AOP在类中调用方法,不会经过代理逻辑,只有当使用代理对象调用方法才会经过代理逻辑配置类: A(){ B(); } B(){ } 执行A方法生成Bean->代理逻辑->判断当前是不是自己(是)->A里面调用B方法->代理逻辑)->判断当前是不是自己(不是)->走beanFacory获取B->代理逻辑->判断当前是不是自己(是)->走自己的逻辑执行B方法
多个bean
是
根据推断出来的构造方法进行实例化
PROPAGATION_REQUIRES_NEW
往beanFactory中注入AnnotationAwareAspectJAutoProxyCreator对应的BeanDefinition
获取并解析@Value上的注解,进行解析并返回
onRefresh()提供给AbstractContext的子类进行扩展
触发同步器的afterCompletion()
把candidates返回
把加了@bean的方法加到configClass的beanMethods属性中
否
destroyBeans()
autowire为AUTOWIRE_CONSTRUCTOR
构造一个TransactionStatus
AnnotationAwareAspectJAutoProxyCreator是一个InstantiationAwareBeanPostProcessor
获取MapperScan注解信息
经上述步骤判断是否确定了构造方法和构造方法参数值
抛出异常
doBegin()
自动候选者解析器,用来判断某个bean,针对当前依赖是否能进行自动注入
查看@Transactional注解是否指定了TransactionManager,如果没有,则取容器中TransactionManager类型的bean
判断当前构造是否是无参的
执行其他的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
生成BeanDefinition
添加ignoreDependencyInterface
判断descriptor的类型
构造AnnotatedBeanDefinitionReader
添加resolvableDependencies
MapperScannerConfigurer是一个BeanDefinitionRegistryPostProcessor,容器初始化的时候会执行postProcessBeanDefinitionRegistry方法
BeanDefinition的后置处理
判断候选者构造方法是不是只有一个,且没有指定构造方法参数
配置类上加上@EnableTransactionManagement注解
一个bean
先找到所有的注入点
提交子流程
实例化
finishRefresh();BeanFactory初始化完成中,就到了spring启动的最后一步
根据依赖描述上有@Lazy注解,直接生成一个代理对象返回,调用代理对象的方法时,才会调用以下方法
设置ApplicationContext的lifecycleProcessor
将代理对象,被代理对象,当前执行的方法,方法参数,被代理的类,chain,当前正在执行代理类的方法对象组合成一个CglibMethodInvocation对象
开始扫描
返回null
存在
candidates分为两种情况:1.只有一个required=true的构造方法2.多个required=false的构造方法和一个无参构造方法
会处理bean中的@Resource注解,并进行依赖注入
MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,spring在扫描BeanDefinition时会执行registerBeanDefinitions()方法
获取当前执行方法的@Transactional注解的信息TransactionAttribute
解析AppConfig类
向BeanFacotry添加AutowiredAnnotationBeanPostProcessor对应的BeanDefinition
调用processImports()方法处理导入类
对于TransactionManager有一个限制,必须是PlatformTransactionManager
InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用
Map
报错
发布ContextRefreshedEvent事件
向BeanFacotry添加ConfigurationClassPostProcessor对应的BeanDefinition
调用AbstractPlatformTransactionManager.getTransaction()方法,实际上这个方法就是真正的开启事务
对候选者的构造方法进行排序,按照构造方法的参数个数进行降序排序,参数多的排在前面
返回这个唯一的构造方法
方法
初始化前
使得ApplicationListenerDetector为列表最后一个BeanPostProcessor
记录disposable的bean
1. 通过@MapperScan导入了MapperScannerRegistrar类2. MapperScannerRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以Spring在启动时会调用MapperScannerRegistrar类中的registerBeanDefinitions方法3. 在registerBeanDefinitions方法中定义了一个ClassPathMapperScanner对象,用来扫描mapper4. 设置ClassPathMapperScanner对象可以扫描到接口,因为在Spring中是不会扫描接口的5. 同时因为ClassPathMapperScanner中重写了isCandidateComponent方法,导致isCandidateComponent只会认为接口是备选者Component6. 通过利用Spring的扫描后,会把接口扫描出来并且得到对应的BeanDefinition7. 接下来把扫描得到的BeanDefinition进行修改,把BeanClass修改为MapperFactoryBean,把AutowireMode修改为byType8. 扫描完成后,Spring就会基于BeanDefinition去创建Bean了,相当于每个Mapper对应一个FactoryBean(单例的)9. 在MapperFactoryBean中的getObject方法中,调用了getSqlSession()去得到一个sqlSession对象,然后根据对应的Mapper接口生成一个代理对象10. sqlSession对象是Mybatis中的,一个sqlSession对象需要SqlSessionFactory来产生11. MapperFactoryBean的AutowireMode为byType,所以Spring会自动调用set方法,有两个set方法,一个setSqlSessionFactory,一个setSqlSessionTemplate,而这两个方法执行的前提是根据方法参数类型能找到对应的bean,所以Spring容器中要存在SqlSessionFactory类型的bean或者SqlSessionTemplate类型的bean。12. 如果你定义的是一个SqlSessionFactory类型的bean,那么最终也会被包装为一个SqlSessionTemplate对象,并且赋值给sqlSession属性13. 而在SqlSessionTemplate类中就存在一个getMapper方法,这个方法中就会利用SqlSessionFactory来生成一个代理对象
没有传入构造方法,那么则获取当前BeanDefition的beanClass的所有的构造器作为候选者
执行bean的销毁方法,清除容器中的单例bean相关缓存
如果执行业务方法没有异常,执行finally中的方法进行提交
检查某个bean是不是ApplicationListener,如果是,加到ApplicationContext中
至此所有的BeanFactoryPostProcessor的逻辑都执行完了,主要做的事情就是得到BeanDefinition注册到BeanFactory中
将PlatformTransactionManager,TransactionAttribute,TransactionStatus构造成一个TransactionInfo对象,并返回TransactionInfo对象
创建BeanFactory
该构造方法是不是无参构造方法
PROPAGATION_NESTED
但是不包含事务对象,也不会去建立数据库连接
把当前构造器添加到candidates
在构造过程中,添加@Component注解对应的AnnotationTypeFilter到includeFilters中
代理对象执行方法子流程
处理当前类所有实现的接口,查看接口中是否存在@Bean的默认方法
计算构造方法参数个数最少数量minNrOfArgs
往spring注册InfrastructureAdvisorAutoProxyCreator的BeanDefinition
合并BeanDefinition
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet())
MapperScannerRegistrar.registerBeanDefinitions()
处理子流程
整个ConfigurationClass解析结束之后,就会把configurationClasses中所有的ConfigurationClass取出来
@Import({MapperScannerRegistrar.class})
解析配置类的BeanFactoryPostProcessor,会进行扫描
生产代理对象子流程
把当前构造器记录为requiredConstructor
解析出@PropertySources注解解析出Properties文件路径,封装成Properties对象,并添加到Environment对象中
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
如果本次开启事务当前线程第一次开启事务,那么获得的事务对象中没有数据库连接对象如果本次开启事务当前线程还有事务没有提交,那么获得事务对象就有数据库连接
判断是否有事务挂起
初始后,这里会进行AOP
通过@MapperScan导入了MapperScannerRegistrar类MapperScannerRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以Spring在启动时会调用MapperScannerRegistrar类中的registerBeanDefinitions方法在registerBeanDefinitions方法中生成了一个MapperScannerConfigurer类型的BeanDefinition而MapperScannerConfigurer实现了实现了BeanDefinitionRegistryPostProcessor接口,所以Spring在启动过程中时会调用它的postProcessBeanDefinitionRegistry()方法在postProcessBeanDefinitionRegistry方法中会生成一个ClassPathMapperScanner对象,然后进行扫描后续的逻辑和1.3.2版本一样
事务挂起就是把事务的连接对象,同步器,事务名字,隔离级别记录到SuspendedResourcesHolder对象中,并把TransactionSynchronizationManager中的信息全部清空,清空是为了用来记录下一个事务的信息
生成对应的ImportBeanDefinitionRegistrar实例
初始化
判断是不是一个配置类
ProxyTransactionManagementConfiguration是一个普通的类
只有1个
往spring容器定义了BeanFactoryTransactionAttributeSourceAdvisor,TransactionAttributeSource,TransactionInterceptor这三个bean
调用下面的方法,将Map的values返回
MapperScannerConfigurer.postProcessBeanDefinitionRegistry()
计算构造方法参数值和构造方法参数的匹配程度
进行推断构造方法
@Import一个ImportSelector,spring在扫描配置的BeanDefinition的时候会执行这个类的selectImports方法,将返回的类名重新作为@Import进去的类进行解析
遍历未再次处理过的ConfigurationClass
initApplicationEventMulticaster();如果BeanFactory中存在一个叫\"applicationEventMulticaster\
进行扫描
如果是属性注入,就是属性名字
判断当前bean是否要进行AOP,比如,当前bean是PointCut,Advise,Advisor等那就不需要AOP
如果还有多个
initMessageSource();如果BeanFactory中存在一个叫\"messageSource\
根据注入点类型寻找bean
调用suspend()方法把当前事务挂起,并返回suspendedResources对象
在配置类上加上@EnableAspectJAutoProxy这个注解
processBeanDefinitions(beanDefinitions)
直接返回该bean,如果是class对象,调用getBean生成该对象
spring启动流程
判断required属性是否为true
提交事务
判断构造方法上是否有@Autowired注解
处理@Import注解
添加到configClass对象的importBeanDefinitionRegistrars属性中
isRequired
如果传入构造方法,则把传入的构造器作为候选者
注册一些默认的类型转换器
执行代理对象的方法会经过DynamicAdvisedInterceptor的逻辑
开始创建事务
设置DynamicAdvisedInterceptor为callbacks
不存在
缓存该构造方法和构造方法参数值(new Object[0])
调用CglibMethodInvocation的proceed方法
MapperFactoryBean.getObject()
设置当前数据库连接的隔离级别
返回空数组
代理对象执行方法时
遍历BeanDefinition
处理@ImportResource注解
普通类
会把当前的一些事务信息设置到TransactionSynchronizationManager中
是否存在@Value注解
遍历每个注入点
其他
初始化后
刷选当前bean匹配的Advise,Advisor
意思是,现场程序员手动指定了几个构造方法的参数值,所以当前BeanDefinition对应的beanClass的所有构造方法的参数个数至少大于程序员设置的参数个数
验证evenroment中是否包含必要属性
针对当前的BeanDefinition是否缓存了构造方法和参数值
如果没有优先级,那么使用descriptor.getDependencyName()来确定唯一的bean(byName)
构造并返回TransactionStatus对象,TransactionStatus对象中存在suspendedResources对象,并更新TransactionSynchronizationManager中的信息
根据name去寻找bean
obtainFreshBeanFactory()
BeanDefinition里指定了构造方法的参数值
利用reader注册AppConfig为BeanDefinition,类型为AnnotatedGenericBeanDefinition
将defaultConstructor加入到candidates
AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口,在spring扫描BeanDefinition时,会执行这个类的registerBeanDefinitions()方法
PROPAGATION_NOT_SUPPORTED,把当前事务挂起,然后以非事务方式运行
注册MapperScannerConfigurer的BeanDefinition到spring容器中
启动ApplicationContext
调用DataSourceTransactionManager.doGetTransaction()方法,得到一个事务对象,这个对象可能持有也可能没有持有数据库连接对象
处理当前的ConfigurationClass的importBeanDefinitionRegistrars属性,执行registerBeanDefinitions方法来进行BeanDefinition的注册
调用数据库对象的commit()
递归调用processConfigurationClass()方法处理当前类,会把这些类加到configurationClasses中
如果有则把挂起的事务重新设置到TransactionSynchronizationManager中去,并执行同步器的resume()方法
prepareRefresh()
根据当前执行方法的对应的类刷新对应的Advisor
继续遍历下一个候选者
实例化,得到原始对象
会处理bean中的@Autowired注解,并进行依赖注入
执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
非原型的ban
@Import一个ImportBeanDefinitionRegistrar,spring在扫描配置的BeanDefinition的时候会执行这个类的registerBeanDefinitions方法,将BeanDefinition注册到spring容器中
处理当前的ConfigurationClass的importResource属性,解析导入的xml文件
如果当前的ConfigurationClass有@Bean方法,通过该方法生成BeanDefition并注册
从BeanFactory中找到所有类型为BeanFactoryPostProcessor的beanName,而这些BeanFactoryPostProcessor包含了上面的BeanDefinitionRegistryPostProcessor
取@Primary注解的bean
直接绑定某个类型和对应的bean对象,在自动注入的时候,会优先从这个map中获取类型对应的对象注入
doBegin()子流程
解析@Bean,@Import等注解得到BeanDefinition并注册
执行BeanFactory后置处理器
填充属性
其他值则会在当前事务运行
spring容器bean的销毁
是否找出了唯一的bean
没有@Primary注解,则看bean对应的类上的@Priority注解,选取优先级最高的,注解上数值越低优先级越高
getBean方法是否指定了构造方法的参数值
扫描就是执行BeanFactory后置处理器过程中进行的
开始执行MethodInterceptor逻辑
getBean方法调用的时候指定了构造方法的参数值
如果注入点是required的,也就是这个注入点是必须的,那么就会报错
生成一个joinpointIdentification作为事务的名字
把导入的路径添加到configClass的importedResources属性中
再判断是否符合Qualifier
默认情况下RuntimeException和Error会回滚
ImportBeanDefinitionRegistrar
如果两者其中一个为空,则继续进行下面步骤
2.0.5版本
根据type找到bean
没有指定
AspectJAutoProxyRegistrar.registerBeanDefinitions()
从多个bean中确定出唯一的bean
根据名字刷选,帅选出唯一的bean
生成代理类
添加一些bean到单例池中
如果事务对象中没有持有数据库连接对象,那么则调用DataSource获取一个数据库连接对象,并设置到事务对象中去
添加bean的后置处理器ApplicationContextAwareProcessor
选出匹配程度值最小的构造方法
当前候选者的参数个数小于minNrOfArgs,则该候选者不匹配,继续遍历下一个候选者
遍历所有内部类
给原始对象填充属性
解析AppConfig的BeanDefinition
处理@Bean注解
spring启动bean的生命周期
Optional
属性类型
递归调用processConfigurationClass()方法处理新的配置类
判断某个bean是不是XXXaware接口的实现类,是则执行对应的aware回调
进一步对扫描出来的BanDefinition进行处理
从BeanFactory中找出类型为BeanDefinitionRegistryPostProcessor的beanName,也就是ConfigurationClassPostProcessor,然后调用BeanFactory.getBean()方法得到实例对象
this.doScan(basePackages)
回滚事务子流程
AutoProxyRegistrar.class.getName()ProxyTransactionManagementConfiguration.class.getName()
PROPAGATION_NEVER
super.doScan(basePackages)
是否存在required为true的构造器
进行注入
每个ConfigurationClass解析完之后,就会把ConfigurationClass对象添加到configurationClasses
构造Enhancer对象
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry)
创建事务子流程
解析配置类
CommonAnnotationBeanPostProcessor父类的InitDestroyAnnotationBeanPostProcessor会去寻 找@PostConstuct和@PreDestroy注解的方法
@Import(AspectJAutoProxyRegistrar.class)
@EnableTransactionManagement
遍历每个构造方法
设置表达式解析器StandardBeanExpressionResolver
判断事务对象中是否持有数据库连接对象
获取类中所有的构造方法,记录为rawCandidates
触发同步器的beforeCommit()
创建TransactionStatus对象子流程
先判断是不是isAutowireCandidate
定义一个disposableBean适配器,适配各种类型
直接生成一个ObjectFactory对象
@EnableAspectJAutoProxy
把这个bean直接进行注入
配置ProxyFactory
持有
finishBeanFactoryInitialization(beanFactory);完成BeanFactory的初始化,主要就是实例化非懒加载的单例bean
判断rawCandidates的大小是否等于1,表示当前是否只有一个构造方法
doClose()
创建代理对象子流程
则和@Autowired一样的实现原理,先byType,再byname
调用this.reader.loadBeanDefinitions(configClasses)再次处理ConfigurationClass,得到beanDefinition并注册
找到几个bean
不管是否存在@Component注解
处理AppConfig,调用ConfigurationClass对象的processConfigurationClass()方法
candidates是否为空,表示是否存在@Autowired注解的构造器
初始化一个扫描器
递归调用processImports()方法处理得到的类
持有就代表当前线程存在事务
被@Autowired注解的方法
被@Autowired注解的属性
基于构造方法参数,先byType再byName,以及BeanDefinition中所设置的参数一起得到当前构造方法合适的参数值,封装为一个ArgumentsHolder对象
把获得的数据库连接对象通过TransactionSynchronizationManager设置到当前线程的ThreadLocal
bean实现DisposableBean或者AutoCloseable接口 @Bean方法声明的bean,且类中有close或者shutDown方法 或者beanDefinition定义了destoryMothod属性 或者bean中定义了@PreDestroy注解的方法
执行完MethodInterceptor逻辑后执行代理对象对应的方法
遍历结束
这个比较简单,就是利用数据库连接对象,设置一个savepoint,比如mysql就支持,在一个事务中,可以在某个位置设置一个savepoint,后续可以只回滚到某个savepoint
有多个构造方法可以使用
触发同步器的afterCommit()
实例化前,判断是否当前beanName设置了TargetSource,可以通过CustomTargetSourceCreators进行设置,如果设置了,直接对TargetSource进行AOP,得到代理对象,不再进行后期生命周期处理
缓存上面推断出来的构造方法
defaultConstructor是否为空
@Autowired获取注入对象过程
判断有没有通过getBean方法指定构造方法的参数值
AppConfig类中是否存在内部类
基于bean的原始对象和匹配的Advise,Advisor,创建代理对象,并返回
设置数据库连接的timeOut
是否超过1个
创建bean的时候byType注入,会执行MapperFactoryBean父类SqlSessionDaoSupport的,setSqlSessionFactory()和setSqlSessionTemplate()方法,来对sqlSessionTemplate属性进行赋值
将commonInterceptors和specificInterceptors整合到一起
spring事务
context.close()
递归解析父类
开始遍历候选者
调用数据库对象的rollback()
如果执行业务方法异常,会进行回滚,然后执行finally中的方法再将异常抛出
不持有就表示当前线程不存在事务
记录启动时间
构造ClassPathBeanDefinitionScanner
需要回滚
prepareBeanFactory(beanFactory)
doResolveDependency(descriptor)
获取mybatis生成的代理对象
没有找到
如果内部类也是配置类
设置BeanFactory的类加载器
bean的初始化后BeanPostProcessor.postProcessAfterInitialization()
执行所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
设置dependencyComparator
Collection
执行selectImports()方法得到多个类
加了@Transactional注解的类或者方法加了@Transactional注解的类,都会生成代理对象的Bean
处理@PropertySources注解
超过1个
推断构造方法
得到一个TransactionStatus对象
ImportSelector
执行LifeCycleBean
Bean的生命周期
如果是setter方法,那就是参数名字
指定了
@Import一个普通类,spring在扫描BeanDefinition时,会将这个普通类作为配置类进行解析
构造一个BeanFactory,为DefaultListableBeanFactory
实际上,在每次遍历构造方法时,如果发现前面已经选定了一个候选者,并且找到合适的参数,当前的构造方法的参数个数小于选定的候选者的参数个数,则退出循环
寻找@Resource注入点
如果存在
零个bean
getSqlSession().getMapper(this.mapperInterface)
如果某个类实现了这个集合的接口,那么对应的setter方法,就不会用来在byType和byName进行注入
比较器,可以用来排序,获取@Priority,Ordered接口的值,@Order的值
判断导入的class的类型
判断descriptor.getDependencyType()
执行Aware
实例化前
postProcessBeanFactory(beanFactory)
用来解析单例bean中被@EventListener注解的方法,并封装为ApplicationListenner添加到ApplicationContext
抛异常
把AppConfig封装成一个ConfigurationClass
\"environment\":environment对象\"systemProperties\":System.getProperty()返回的map对象\"systemEnvironment\":System.getenv()返回的map对象
将无参构造器设置为defaultConstructor
设置数据库连接的autoCommit为false
@MapperScan(\"com.lian.mybatistest.mapper\")
如果参数个数匹配,则把所有的参数封装成一个ArgumentsHolder对象
加载类
AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()方法会将加了@Aspect注解的类对应的方法封装成advisors
构造一个ProxyFactory
扫描指定路径得到BeanDefinition集合
执行spring扫描BeanDefinition的逻辑
初始化BeanFactory
取优先级最高的bean
处理@ComponentScan注解
AOP流程
先判断beanFactory是否存在注入点名字对应的bean
获取类对应的建议
调用ObjectFactory对象getobject()方法时时调用
scanner.scan()
方法参数类型
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); definition.setBeanClass(this.mapperFactoryBeanClass);
@Import(TransactionManagementConfigurationSelector.class)
两者都确定了,通过构造方法和参数进行反射实例化出对象
得到匹配的MethodInterceptor封装为List<Object> chain
添加propertyEditorRegistrar:ResourceEditorRegistrar
从多个bean的BeanDefinition中选取带有@Primary注解的,如果有多个@Primary,则报错
判断当前异常是否需要回滚
找出了,也要判断是否是class对象,如果是,则调用getBean方法生成bean,返回
AutoProxyRegistrar是一个ImportBeanDefinitionRegistrar
invokeBeanFactoryPostProcessors(beanFactory)
执行还没执行过BeanFactoryPostProcessor的postProcessBeanFactory()方法
向BeanFacotry添加EventListenerMethodProcessor对应的BeanDefinition
bean.destroy()
向BeanFacotry添加CommonAnnotationBeanPostProcessor对应的BeanDefinition
扫描得到BeanDefinition并注册
是否存在@Component注解
收藏
收藏
0 条评论
下一页