当前位置: 首页 > news >正文

示范校建设专题网站四平卫生学校动叫建个网站刷排名

示范校建设专题网站四平卫生学校,动叫建个网站刷排名,wordpress机械模板下载地址,wordpress搜索插件提前写在前面 前段时间做过一个项目#xff0c;期间用到了动态数据源dynamic-datasource#xff0c;经历了dbcp2的数据库连接池没有生效到排查定位、MyBatis多种数据库产品兼容、手写MyBatis拦截器等事情。 花费了好久#xff0c;一直在打磨这篇文章#xff08;不知道花费这么长…写在前面 前段时间做过一个项目期间用到了动态数据源dynamic-datasource经历了dbcp2的数据库连接池没有生效到排查定位、MyBatis多种数据库产品兼容、手写MyBatis拦截器等事情。 花费了好久一直在打磨这篇文章不知道花费这么长时间写文章有没有意义但互联网总得留下点儿什么吧~。最终千呼万唤始出来。本文就从源码的角度来系统地看看原理是什么能学到些什么。如有说的不正确的地方欢迎指正。 目录 写在前面一、环境说明二、为什么如何做三、动态数据源部分一动态数据源加载、连接池创建 四、MyBatis部分一 MyBatis核心组件加载二MapperProxy初始化三连接池的使用、数据库厂商加载、拦截器生效 五、收获六、附录plantuml脚本activity_baomidou_dynamicdatasource.pumlactivity_mybatis_sqlsessionfactorybean.pumlactivity_mybatis_mapperproxy.pumlactivity_mybatis_conn_interceptor.pumlclass_baomidou.pumlclass_mybatis.puml 写在后面系列文章 一、环境说明 名称说明mybatis版本mybatis-3.4.6.jarmybatis-spring版本mybatis-spring-1.3.1.jarmybatis-spring-boot版本mybatis-spring-boot-autoconfigure-1.3.0.jardynamic-datasource-spring-boot-starter版本dynamic-datasource-spring-boot-starter-3.5.2.jarcommons-dbcp2版本commons-dbcp2-2.8.0.jarIDEA编辑器2019PlantUML插件IDEA / VsCode插件 二、为什么如何做 说正题前我们先思考一下为什么要看源码 我想可能有几种场景 1、出问题了不得不看。 比如在项目中引入了什么包、配置或者做了什么改动导致项目无法启动或者报错了 2、求知欲。有疑问带着问题看。 比如本文将要讨论的dbcp2连接池是什么时机创建的如何创建的又是怎么使用的MyBatis拦截器插件是如何生效的等等 3、面试。 不过比起八股文自己研究一下体会会更深。那看源码我们能收获什么 个人认为看源码可以去切实地体会优秀的代码设计了解高手是怎么做的包括设计模式的运用、扩展点、设计原则等等。思考如果自己以后遇到类似问题该如何运用。不熟悉设计模式这部分内容的朋友可以去参考这篇文章【GitHub】- design-pattern设计模式 另外看源码笔者还有一个提示不要一下子要求全搞懂否则你会越陷越深… 看到最后不知所云。根据当下的水平逐步丰富自己的体系建议带着问题带着疑问点到为止问题搞懂不要无限蔓延 那究竟该如何看这里我谈一谈自己的见解正文内容也是这么做的。 稍微扩展一下延展到如何学习一个新的框架或者新的知识点 1、通读官方文档、GitHub的README 知道这个框架是做什么的主要用于解决什么问题了解框架的架构图 2、结合官方Demo熟悉基本操作API 3、自己动手 写Demo本地调试。梳理流程主要包括2部分内容类图和活动图 画类图能让你快速全面地了解到这个类是干什么用的有什么样的体系继承、实现、依赖以及关联关系 画活动图能让你知道这些类的调用关系、这些类是如何相互作用使用的。不熟悉类图和活动图的这部分朋友可以去参考这篇文章【UML】- 类图 看源码首先看什么能最快地找到突破口 我认为 首先看它的pom.xml看依赖关系pom中有什么jar包可能就会具备哪些功能 其次看源码的包命名优秀的代码内聚做的比较好 然后从resource开始着手可能有一些配置需要提前了解好了接下里我们回归正题。 以下从2个部分开始说主要包括动态数据源和MyBatis。 三、动态数据源部分 一动态数据源加载、连接池创建 首先找到 dynamic-datasource-spring-boot-starter-3.5.2.jar 我们在resource下找到了META-INF/spring.factories咦这是什么这不就是自动装配么。好了找到切入口了。 org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration看看 DynamicDataSourceAutoConfiguration 干了什么事情 # DynamicDataSourceAutoConfiguration 1.将 yml 中的配置信息数据源url/driver、连接池等等配置信息构建成Bean加入到Spring容器 2.通过 Import 导入creator的自动配置类 DynamicDataSourceCreatorAutoConfiguration进行creator初始化2.1 创建一个 DefaultDataSourceCreator(ListDataSourceCreator dataSourceCreators)构造注入dataSourceCreators与DataSourceCreator绑定关系也就是dbcp2的creator2.2 判断classpath中有dbcp2的包创建 Dbcp2DataSourceCreator 3.创建 YmlDynamicDataSourceProvider()3.1 通过构造方法和 dataSourcePropertiesMap 进行了绑定3.1 通过继承属性注入 DefaultDataSourceCreator和creator进行了绑定 4.创建 DynamicRoutingDataSource 路由4.1 Autowired 属性注入 provider也就是 YmlDynamicDataSourceProvider4.2 实现了InitializingBean初始化Bean时会调用afterPropertiesSet我们先梳理一下这里边的几个绑定关系 DynamicRoutingDataSource 路由包含一个 YmlDynamicDataSourceProvider YmlDynamicDataSourceProvider 中有 dataSourcePropertiesMap 和 DefaultDataSourceCreator DefaultDataSourceCreator 中有 List包含了dbcp的creator。 该初始化的进行初始话该绑定的关系的绑定关系。 接下来我们重点看 DynamicRoutingDataSource#afterPropertiesSet() 动态数据源加载的过程也就是连接池的创建过程。 # DynamicRoutingDataSource#afterPropertiesSet() 1.调用 provider#loadDataSources()# YmlDynamicDataSourceProvider 2.调用 defaultDataSourceCreator#createDataSource# DefaultDataSourceCreator 3.调用 dbcp2#doCreateDataSource(dataSourceProperty)# BasicDataSource 4.调用 dbcp2的连接池去创建数据源 dataSource#start()4.1 for循环配置文件中的 initialSizeconnectionPool.addObject() 添加到LinkedBlockingDeque中至此连接池就创建完毕了。 以下是活动图和类图 温馨提示鼠标右键-》在新标签页中打开图片可查看高清图。PlantUML脚本在附录部分 有了类图就很明显了这里面有3个体系 DataSourcespring实现了AbstractDataSource DataSourceCreator DynamicDataSourceProvider相应地对应了有3个抽象类 1.AbstractRoutingDataSource 这个类在连接池创建的时候没用到这里也说一下在获取时为重载DataSource#getConnection 添加一个determineDataSource()获取连接池的操作 具体实现在DynamicRoutingDataSource中2.AbstractDataSourceCreator 抽象连接池创建器这里边抽象出一个 doCreateDataSource(DataSourceProperty dataSourceProperty)由具体的实现类dbcp2、druid、Hikari实现 另外在doCreateDataSource前后做了一些通用逻辑 // 源码 dataSourceInitEvent.beforeCreate(dataSourceProperty) DataSource dataSource doCreateDataSource(dataSourceProperty); dataSourceInitEvent.afterCreate(dataSource)3.AbstractDataSourceProvider 多数据源加载接口默认的实现为从yml信息中加载所有数据源。 抽象出接口就可以扩展一些其他加载数据源的方式四、MyBatis部分 一 MyBatis核心组件加载 首先找到 mybatis-spring-boot-autoconfigure-1.3.0.jar 在resource下找到了META-INF/spring.factories # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration\ org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration看一下MybatisAutoConfiguration做了什么事情。 # MybatisAutoConfiguration 1.AutoConfigureAfter优先注入datasource数据源 2.通过datasource数据源构造方式 SqlSessionFactoryBean绑定了数据源2.1 设置datasource、configuration2.2 由于实现了InitializingBean初始化Bean时会调用afterPropertiesSet2.2.1 处理configuration、添加Interceptor、databaseId、创建事务工厂、解析xml对象最后构建一个DefaultSqlSessionFactory 3.通过sqlsesssionfactory创建sqlSessionTemplate3.1 构造方法中隐藏了一个sqlSessionProxy代理它代理了SqlSession接口通过SqlSessionInterceptor的invoke实现逻辑说明这里SqlSessionTemplate定义了一套操作Mybatis的模板实际上方法的执行调用的都是SqlSession的实现类方法 因为框架想在操作完方法之后处理一些事务的提交、session的关闭等操作实现方式是使用代理Proxy代理SqlSession 以下是活动图 温馨提示鼠标右键-》在新标签页中打开图片可查看高清图。PlantUML脚本在附录部分 二MapperProxy初始化 我们知道接口是无法执行方法的这里MyBatis把所有的mapperInterface代理成了MapperProxy。以下是MapperProxy的创建过程活动图 温馨提示鼠标右键-》在新标签页中打开图片可查看高清图。PlantUML脚本在附录部分 三连接池的使用、数据库厂商加载、拦截器生效 以下是MyBatis操作整体流程活动图 温馨提示鼠标右键-》在新标签页中打开图片可查看高清图。PlantUML脚本在附录部分 我们以一个示例 baseMapper.queryByList(map) 作为入口来说明 执行baseMapper#queryByList()实际上调用的是 mapperproxy#invoke前面提到了mapperproxy代理了baseMapper mapperproxy调用了mapperMethod#execute(sqlSession, args) # MapperMethod 1.根据 SqlCommandType 执行SQL也就是判断 CRUD然后通过SqlSession做相应操作这里的重点来了SqlSession现在是什么SqlSession是SqlSessionTemplate也就是会调用SqlSessionTemplate#selectList 在源码里你会看到接着调用的是 sqlSessionProxy#selectList,sqlSessionProxy我们前面提到过是代理的SqlSessionInvokeHandler是SqlSessionInterceptor 那么此时就会调用SqlSessionInterceptor#invoke# SqlSessionInterceptor 2.这是一个模板的方法进行了3个操作2.1 获取真正要处理的 getSqlSession2.2 执行方法2.3 判断事务操作提交事务2.4 关闭session接下来详细说一下[2.1] getSqlSession()干了什么事情它通过前面创建的 DefaultSqlSessionFactory 创建一系列的组件。 # DefaultSqlSessionFactory 2.1.1根据datasource创建tx事务transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit) 2.1.2.创建Executor执行器configuration.newExecutor(tx, execType)2.1.2.1 这个executor执行器会经过拦截器链分页、自定义的属性填充的包装这里又是一个Plugin的代理会代理executor里面的方法在真正方法执行前先执行这些拦截器的操作2.1.2.2 最终返回一个DefaultSqlSession对象当执行[2.2] 的方法时通过反射的方式调用就是DefaultSqlSession#selectList #DefaultSqlSession 2.2.1 这里边会去获取到databaseId的sql 2.2.2 先去执行拦截器链中的拦截器分页、属性填充 2.2.3 要获取Connection2.2.3.1 从事务中获取datasource此时的datasource在DynamicRoutingDataSource的datasourceMap中2.2.3.2 拿到datasource后dbcp2的datasource会调用getConnection从 LinkedBlockingDeque#pollXxx()以下是MyBatis的类图 看看类图你至少知道什么是datasource、什么是connection、什么是sqlsession对他们的关系有了进一步的理解了吧。 温馨提示鼠标右键-》在新标签页中打开图片可查看高清图。PlantUML脚本在附录部分 五、收获 面向接口编程抽象类实现通用逻辑也可以通过模板的方式实现通用逻辑一些自动配置我们可以通过starter自动装配实现关系的构建可以通过Bean初始化去实现InitializingBean进而通过属性或者构造方法的方式去注入一些你需要的Bean可以通过注入Event的这种方式去做一个before和after的事情也可以通过代理的方式实现优秀名的命名、编码风格 … 六、附录plantuml脚本 activity_baomidou_dynamicdatasource.puml startuml skinparam style strictuml skinparam sequenceMessageAlign direction skinparam roundcorner 20 skinparam sequenceParticipant underline autoactivate ontitle 【动态数据源加载及连接池创建】活动图baomidou participant ddsa_config (C,#ADD1B2) DynamicDataSourceAutoConfiguration note over of ddsa_config #aqua自动装配核心Bean创建的入口 end noteparticipant dds_properties (C,#ADD1B2) DynamicDataSourceProperties participant ds_property (C,#ADD1B2) DataSourceProperty note over dds_properties, ds_propertyyml属性对应的Bean内外层 end noteparticipant dds_creator_a_config (C,#ADD1B2) DynamicDataSourceCreatorAutoConfiguration note over of dds_creator_a_configcreator自动配置 end noteparticipant ads_creator (A,#A8DEDF) AbstractDataSourceCreator participant dds_creator (C,#ADD1B2) DefaultDataSourceCreator participant dbcp2ds_creator (C,#ADD1B2) Dbcp2DataSourceCreator note over dds_creator_a_config, dbcp2ds_creatorcreator体系 end noteparticipant ads_provider (A,#A8DEDF) AbstractDataSourceProvider participant ydds_provider (C,#ADD1B2) ymlDynamicDataSourceProvider note over of ydds_provider #aqua组件的关系绑定 end note note over ads_provider, ydds_providerprovider体系 end noteparticipant drds (C,#ADD1B2) DynamicRoutingDataSource note over of drds #aqua动态数据源加载入口 end notedbcp2 participant basic_ds (C,#ADD1B2) BasicDataSource note over of basic_dsdbcp2连接池 end note- ddsa_config: dynamic-datasource-spring-boot-starter-3.5.2.jar 自动装配 META-INF/spring.factories\n EnableAutoConfigurationc.b.d.d.s.b.autoconfigure.DynamicDataSourceAutoConfiguration yml配置文件的加载以及初始化group yml配置构建成Bean加入spring容器ddsa_config - dds_properties: EnableConfigurationPropertiesdds_properties - ds_property: private MapString, DataSourceProperty datasource \n new LinkedHashMap()ds_property -- ddsa_config: yml填充后加入spring容器 endgroup Import导入creatorddsa_config - dds_creator_a_config: Importgroup creator初始化group 创建默认的creatordds_creator_a_config - dds_creator_a_config: dataSourceCreator(ListDataSourceCreator dataSourceCreators)\ncolor red 与DataSourceCreatordbcpCreator绑定关系dds_creator_a_config - dds_creator: new DefaultDataSourceCreator()dds_creator -- dds_creator_a_config: color red提供了createDataSource(dataSourceProperty)方法endgroup 创建dbcp2的creatordds_creator_a_config - dds_creator_a_config: dbcp2DataSourceCreator()dds_creator_a_config - dbcp2ds_creator: new Dbcp2DataSourceCreator()dbcp2ds_creator -- dds_creator_a_config: color red提供了 doCreateDataSource(DataSourceProperty dataSourceProperty) 方法endgroup 创建其他的creator(ConditionalOnClass(BeeDataSource.class))dds_creator_a_config - dds_creator_a_config: ...endenddds_creator_a_config -- ddsa_config: DynamicDataSourceCreatorAutoConfiguration 被创建 endgroup 构造方法 注入 DynamicDataSourceProperties 和 ListDynamicDataSourcePropertiesCustomizerddsa_config - ddsa_config: DynamicDataSourceAutoConfiguration(properties, dataSourcePropertiesCustomizers)\n color red目的是拿到yml中的配置为其他Bean传参 endgroup 创建YmlDynamicDataSourceProviderddsa_config - ydds_provider : ymlDynamicDataSourceProvider(),\n new对象把datasource这个Map(每一个数据源)作为构造参数传入, color red相当于和dataSourcePropertiesMap进行了绑定ydds_provider - ads_provider: Autowigreen DefaultDataSourceCreator defaultDataSourceCreator\n属性注入color red相当于和creator进行了绑定ads_provider -- ydds_providerydds_provider -- ddsa_config: color red提供loadDataSources()方法 endgroup 创建 DynamicRoutingDataSource 路由ddsa_config - drds: dataSource()\n new对象依据DynamicDataSourceProperties的属性设置自身,比如primary属性group Autowired属性注入providersdrds - drds: Autowired ListDynamicDataSourceProvider providers color red此处的provider就是创建YmlDynamicDataSourceProviderenddrds -- ddsa_config: color red由于实现了InitializingBean提供 afterPropertiesSet() 方法连接池创建group #EEE 实现了InitializingBean重写afterPropertiesSetdrds - drds #aqua: Override afterPropertiesSetdrds - ydds_provider: provider.loadDataSources()ydds_provider - ads_provider: createDataSourceMap(dataSourcePropertiesMap)ads_provider - dds_creator: createDataSource(DataSourceProperty dataSourceProperty)dds_creator - ads_creator: createDataSource(DataSourceProperty dataSourceProperty)ads_creator - ads_creator: color red __abstract doCreateDataSource(dataSourceProperty)__\n color red由连接池实现,以dbcp2为例ads_creator - dbcp2ds_creator: doCreateDataSource(DataSourceProperty dataSourceProperty)dbcp2ds_creator - basic_ds: start()group #EEE 真正创建连接池basic_ds - basic_ds: createDataSource()basic_ds - basic_ds: color redfor循环连接池initialSize\n color redconnectionPool.addObject()\r color red添加到LinkedBlockingDeque中endbasic_ds -- drdsend endendumlactivity_mybatis_sqlsessionfactorybean.puml startuml skinparam style strictuml skinparam sequenceMessageAlign direction skinparam roundcorner 20 skinparam sequenceParticipant underline autoactivate ontitle 【MyBatis核心组件加载】活动图 ibatis participant mba_config (C,#ADD1B2) MybatisAutoConfiguration note over of mba_config #aqua自动装配核心Bean创建的入口 end notespring participant dsa_config (C,#ADD1B2) DataSourceAutoConfiguration participant ssf_bean (C,#ADD1B2) SqlSessionFactoryBean note over of ssf_bean #aqua构建SqlSessionFactory的入口 end notemybatis participant ss_template (C,#ADD1B2) SqlSessionTemplate participant ssf_builder (C,#ADD1B2) SqlSessionFactoryBuilder participant dss_factory (C,#ADD1B2) DefaultSqlSessionFactory note over ssf_bean, dss_factorySqlSession相关 end note- mba_config: mybatis-spring-boot-autoconfigure-1.3.0.jar 自动装配 META-INF/spring.factories\n EnableAutoConfigurationo.m.s.b.autoconfigure.MybatisAutoConfiguration 加载yml配置文件及初始化group 优先注入 DataSourceAutoConfigurationmba_config - dsa_config: AutoConfigureAfterdsa_config -- mba_config endgroup 构造方法方式 给私有属性赋值mba_config - mba_config: MybatisProperties\n ObjectProviderInterceptor[]\n ResourceLoader\n ObjectProviderDatabaseIdProvider\n ObjectProviderListConfigurationCustomizer) endgroup #EEE 创建 SqlSessionFactory(DataSource dataSource)mba_config - mba_config: sqlSessionFactory(DataSource dataSource), new对象创建 SqlSessionFactoryBean\n//设置setDataSource、setConfiguration、\n//setPlugins、setDatabaseIdProvider、setMapperLocations(解析classpath:/mapper/*Mapper.xml)mba_config - ssf_bean: getObject()group #EEE 创建SqlSessionFactoryssf_bean - ssf_bean #aqua: afterPropertiesSet()ssf_bean - ssf_bean: buildSqlSessionFactory()\ncolor red//处理configuration\ncolor red//addInterceptor(plugin)\ncolor red//setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource))\ncolor red//创建SpringManagedTransactionFactory\ncolor red//xmlMapperBuilder.parse();\nbuilderAssistant.addMappedStatement(databaseId)\ncreateSqlSource():SqlSourcessf_bean - ssf_builder: this.sqlSessionFactoryBuilder.build(configuration)ssf_builder - ssf_builder: build(config)ssf_builder - dss_factory: color rednew DefaultSqlSessionFactory(config)dss_factory -- ssf_beanendssf_bean -- mba_config endgroup 创建 SqlSessionTemplatemba_config - mba_config: sqlSessionTemplate(SqlSessionFactory sqlSessionFactory)mba_config - ss_template: new SqlSessionTemplate()group #EEE 构造方法ss_template - ss_template: SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, \nExecutorType executorType,\nPersistenceExceptionTranslator exceptionTranslator)\ncolor red//隐藏了一个代理\nthis.sqlSessionProxy (SqlSession) newProxyInstance(\nSqlSessionFactory.class.getClassLoader(),\nnew Class[] { SqlSession.class },\nnew SqlSessionInterceptor());endss_template -- mba_config endendumlactivity_mybatis_mapperproxy.puml startuml skinparam style strictuml skinparam sequenceMessageAlign direction skinparam roundcorner 20 skinparam sequenceParticipant underline autoactivate ontitle 【MyBatis MapperProxy 初始化】活动图 spring participant ab_factory (C,#ADD1B2) AbstractBeanFactory participant mf_bean (C,#ADD1B2) MapperFactoryBean participant ss_template (C,#ADD1B2) SqlSessionTemplate participant config (C,#ADD1B2) Configuration participant mregistry (C,#ADD1B2) MapperRegistry participant mp_factory (C,#ADD1B2) MapperProxyFactory participant mproxy (C,#ADD1B2) MapperProxy - ab_factory: 项目启动service 注入 daoMapperProxy 的初始化 ab_factory - ab_factory: getBean(String name, ClassT requiredType)\n入参示例(configPropertiesDao, com.zhht.dao.ConfigPropertiesDao) ab_factory - ab_factory: getObjectFromFactoryBean(factory, beanName, !synthetic)ab_factory - ab_factory: getObject()ab_factory - mf_bean mf_bean - mf_bean: getObject()\ncolor redgetSqlSession().getMapper(this.mapperInterface) mf_bean - ss_template: getMapper(this.mapperInterface)ss_template - ss_template: getMapper(ClassT type)\n//getConfiguration().getMapper(type, color redthis/color) ss_template - config: getMapper(ClassT type, SqlSession sqlSession)config - mregistry: getMapper(ClassT type, SqlSession sqlSession) mregistry - mp_factory:(MapperProxyFactoryT) knownMappers.get(type)mp_factory - mproxy: newInstance(sqlSession):\ncolor rednew MapperProxyT(sqlSession, mapperInterface, methodCache) mproxy -- ab_factoryendumlactivity_mybatis_conn_interceptor.puml startuml skinparam style strictuml skinparam sequenceMessageAlign direction skinparam roundcorner 20 skinparam sequenceParticipant underline autoactivate ontitle 【连接池使用及数据库厂商加载】活动图 participant mproxy (C,#ADD1B2) MapperProxy participant mmethod (C,#ADD1B2) MapperMethod participant ss_template (C,#ADD1B2) SqlSessionTemplate note over of ss_template #aqua模板方法控制流程 end noteparticipant dss_factory (C,#ADD1B2) DefaultSqlSessionFactory note over of dss_factory #aqua核心组件的创建 end noteparticipant sm_transaction (C,#ADD1B2) SpringManagedTransaction participant config (C,#ADD1B2) Configuration participant mstatement (C,#ADD1B2) MappedStatement participant ds_session (C,#ADD1B2) DefaultSqlSession participant bexecutor (C,#ADD1B2) BaseExecutor participant shandler (C,#ADD1B2) StatementHandler participant interceptor_chain (C,#ADD1B2) InterceptorChain participant interceptor (C,#ADD1B2) Interceptor participant plugin (C,#ADD1B2) Plugin note over interceptor_chain, plugin拦截器 end noteparticipant dr_datasource (C,#ADD1B2) DynamicRoutingDataSource participant dbc2_datasource (C,#ADD1B2) BasicDataSource note over dr_datasource, dbc2_datasource数据源 end note- mproxy: baseMapper.queryByList(map) 入口mproxy - mproxy: Object invoke(Object proxy, \nMethod method, Object[] args) mproxy - mmethod: mapperMethod.execute()group #EEE 根据 SqlCommandType 执行SQLmmethod - mmethod: Object execute(SqlSession sqlSession, Object[] args)\n color red// 难点sqlSession.selectList()\n color red此处的sqlSession是SqlSessionTemplate\n color red// 调用 this.sqlSessionProxy.E selectList(statement, parameter)\n color red 此处的 sqlSessionProxy的 invokeHandler 是SqlSessionInterceptormmethod - ss_template: invoke(因为是代理对象所以要执行 SqlSessionInterceptor.invoke) endss_template - ss_template: invoke(Object proxy, Method method, Object[] args) ss_template - dss_factory: getSqlSession()对象的创建 group 创建 SqlSessiondss_factory - dss_factory: openSession(executorType)group #EEE 创建组件 tx、Executor、DefaultSqlSessiondss_factory - dss_factory: openSessionFromDataSource(ExecutorType execType,\nTransactionIsolationLevel level,\nboolean autoCommit)dss_factory - sm_transaction: color red创建tx\ntransactionFactory.newTransactionsm_transaction -- dss_factorydss_factory - config: color red创建Executor\nconfiguration.newExecutor(tx, execType)group #EEE 创建 Executorconfig - config: 根据 executorTyp\n初始化Batch/Reuse/Simple/CachingExecutorconfig - interceptor_chain: (Executor) pluginAll(executor)\ncolor red包括PageInterceptor、MetaObjectInterceptor等interceptor_chain - interceptor: interceptor.plugin(target)interceptor - interceptor: plugin(Object executor)interceptor - plugin: color redPlugin.wrap(target, this): 代理对象\ncolor red执行的handler是各类interceptorplugin -- configendconfig -- dss_factorydss_factory - ds_session: color red创建SqlSession\nnew DefaultSqlSession(configuration, executor, autoCommit)endendds_session -- ss_template方法的执行 ss_template - ds_session: method.invoke(sqlSession, args)group 具体method的执行ds_session - ds_session: selectList(String statement, Object parameter)ds_session - config: configuration.getMappedStatement(statement)config -- ds_sessionds_session - mstatement: sqlSource.getBoundSql()\ncolor red获取到databaseId的sqlmstatement -- ds_sessionds_session - bexecutor: executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER)group 拦截器执行bexecutor - plugin: invoke()plugin - interceptor: intercept()interceptor -- pluginplugin -- bexecutorendbexecutor - bexecutor: query()bexecutor - bexecutor: queryFromDatabase()bexecutor - bexecutor: prepareStatement()group #EEE 从连接池中获取连接bexecutor - bexecutor: getConnection()bexecutor - sm_transaction: transaction.getConnection()sm_transaction - sm_transaction: openConnectionsm_transaction - dr_datasource: dataSource.getConnection()dr_datasource - dr_datasource: getConnection()dr_datasource - dbc2_datasource: dataSourceMap.get(primary)dbc2_datasource -- sm_transactionsm_transaction -- bexecutorendbexecutor - shandler: handler.query(stmt, resultHandler)shandler -- bexecutorbexecutor -- ds_sessionendds_session -- mmethod事务的提交 ss_template - ds_session: sqlSession.commit(true) ds_session -- ss_templatesession的关闭 ss_template - ds_session: closeSqlSession() ds_session -- ss_templateendumlclass_baomidou.puml startuml skinparam linetype orthotitle 【动态数据源】类图 java namespace javax.sql #EEE {interface Wrapper {unwrap(java.lang.ClassT iface): T TisWrapperFor(java.lang.Class? iface): boolean}interface CommonDataSource { getLogWriter(): PrintWriter setLogWriter(PrintWriter out): void setLoginTimeout(int seconds): void getLoginTimeout(): int getParentLogger(): Logger}interface DataSource {-- getConnection(): Connection getConnection(String username, String password): Connection}Wrapper |-- DataSourceCommonDataSource |-- DataSource } spring namespace org.springframework.beans.factory #EEE {interface InitializingBean { {static} afterPropertiesSet(): void} }namespace org.springframework.jdbc.dataSource #EEE {abstract class AbstractDataSource {}note right: 实现了CommonDataSource的基本操作javax.sql.DataSource |.. AbstractDataSource }baomidou namespace com.baomidou.dynamic.datasource.ds #EEE {abstract class AbstractRoutingDataSource {# {abstract} determineDataSource(): DataSource# {abstract} getPrimary(): String getConnection(): Connection}org.springframework.jdbc.dataSource.AbstractDataSource |--- AbstractRoutingDataSource }namespace com.baomidou.dynamic.datasource #EEE {abstract class DynamicRoutingDataSource {-- Override determineDataSource(): DataSource Override getPrimary(): String}com.baomidou.dynamic.datasource.ds.AbstractRoutingDataSource |-- DynamicRoutingDataSourceorg.springframework.beans.factory.InitializingBean |.. DynamicRoutingDataSource }namespace com.baomidou.dynamic.datasource.provider #EEE {interface DynamicDataSourceProvider { {static} loadDataSources(): MapString, DataSource}abstract class AbstractDataSourceProvider {- defaultDataSourceCreator: DefaultDataSourceCreator- dynamicDataSourceProperties: DynamicDataSourceProperties--# createDataSourceMap(MapString, DataSourceProperty dataSourcePropertiesMap): MapString, DataSource}class YmlDynamicDataSourceProvider {- dataSourcePropertiesMap: MapString, DataSourceProperty-- Override loadDataSources(): MapString, DataSource}DynamicDataSourceProvider |.. AbstractDataSourceProviderAbstractDataSourceProvider |-- YmlDynamicDataSourceProvider }namespace com.baomidou.dynamic.datasource.creator #EEE {interface DataSourceCreator { {static} createDataSource(DataSourceProperty dataSourceProperty): DataSource {static} support(DataSourceProperty dataSourceProperty): boolean}abstract class AbstractDataSourceCreator {# properties: DynamicDataSourceProperties# dataSourceInitEvent: DataSourceInitEvent {abstract} doCreateDataSource(DataSourceProperty dataSourceProperty): DataSource-- createDataSource(DataSourceProperty dataSourceProperty): DataSource}class DefaultDataSourceCreator {- creators: ListDataSourceCreator-- createDataSource(DataSourceProperty dataSourceProperty): DataSource}class BasicDataSourceCreator {- creators: ListDataSourceCreator--static {} Override doCreateDataSource(DataSourceProperty dataSourceProperty): DataSource Override support(DataSourceProperty dataSourceProperty): boolean}note left of BasicDataSourceCreator::staticbuilderClass Class.forName(org.springframework.boot.jdbc.DataSourceBuilder);builderClass Class.forName(org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder);end noteDataSourceCreator |.. AbstractDataSourceCreatorAbstractDataSourceCreator |-- BasicDataSourceCreator }namespace com.baomidou.dynamic.datasource.spring.boot.autoconfigure #EEE {class DataSourceProperty {- type: Class? extends DataSource- driverClassName: String- url: String- username: String- password: String- druid: DruidConfig- dbcp2: Dbcp2Config...}note left of DataSourceProperty::druidNestedConfigurationPropertyend noteclass DynamicDataSourceProperties { {static} PREFIX: String- primary: String- strict: Boolean- datasource: MapString, DataSourceProperty- druid: DruidConfig- dbcp2: Dbcp2Config...}note left of DynamicDataSourceProperties::PREFIXvalue springframework.datasource.dynamicend noteclass DynamicDataSourceCreatorAutoConfiguration {-- dbcp2DataSourceCreator(): Dbcp2DataSourceCreator basicDataSourceCreator(): BasicDataSourceCreator dataSourceCreator(ListDataSourceCreator dataSourceCreators): DefaultDataSourceCreator}class DynamicDataSourceAutoConfiguration {- properties: DynamicDataSourceProperties- dataSourcePropertiesCustomizers: ListDynamicDataSourcePropertiesCustomizer-- ymlDynamicDataSourceProvider(): DynamicDataSourceProvider dataSource(): DataSource Override afterPropertiesSet(): void}com.baomidou.dynamic.datasource.DynamicRoutingDataSource --[hidden] DynamicDataSourcePropertiesDynamicDataSourceProperties - DataSourcePropertyDynamicDataSourceProperties -- DynamicDataSourceAutoConfigurationDynamicDataSourceAutoConfiguration - DynamicDataSourceCreatorAutoConfiguration: Import }endumlclass_mybatis.puml startuml skinparam linetype orthotitle 【MyBatis】类图 java namespace javax.lang #EEE {interface AutoCloseable {-- close(): void} }namespace javax.io #EEE {interface Closeable {-- close(): void}javax.lang.AutoCloseable |-- Closeable }namespace javax.lang.reflect #EEE {interface InvocationHandler {-- invoke(Object proxy, Method method, Object[] args): Object} }namespace javax.sql #EEE {interface Connection {-- prepareStatement(String sql): PreparedStatement setSavepoint(): Savepoint setAutoCommit(boolean autoCommit): void rollback(Savepoint savepoint): void getTransactionIsolation(): int setTransactionIsolation(): void rollback(): void commit(): void Override close(): void}javax.lang.AutoCloseable |-- Connection }spring namespace org.springframework.context #EEE {interface ApplicationListener {-- onApplicationEvent(E event): void} }namespace org.springframework.core.io #EEE {interface Resource {-- exists(): boolean isReadable(): boolean isOpen(): boolean getURL(): URL getFile(): File} }namespace org.springframework.beans.factory #EEE {interface BeanFactory {-- getBean(ClassT requiredType): T isSingleton(String name): boolean isPrototype(String name): boolean}interface FactoryBeanT {-- getObject(): T}interface InitializingBean { {static} afterPropertiesSet(): void} }ibatis namespace org.apache.ibatis #EEE {interface SqlSession {-- getMapper(ClassT type): T getConfiguration(): Configuration getConnection(): Connection selectOne(String statement): T selectList(String statement): ListE select(String statement, ResultHandler handler): void insert(String statement): int update(String statement): int delete(String statement): int commit(): void rollback(): void Override close(): void}interface SqlSessionFactory {-- openSession(): SqlSession getConfiguration(): Configuration}class Configuration {# environment: Environment# objectFactory: DefaultObjectFactory# mappedStatements: MapString, MappedStatement}class SqlSessionTemplate {- sqlSessionFactory: SqlSessionFactory- executorType: ExecutorType- sqlSessionProxy: SqlSession, 代理的是 SqlSessionInterceptor}javax.io.Closeable |-- SqlSessionjavax.sql.Connection --[hidden] SqlSessionSqlSession .. SqlSessionFactory: openSession()SqlSessionFactory .. Configuration: getConfiguration()SqlSessionTemplate .| SqlSession}namespace org.apache.ibatis.binding #EEE {class MapperProxyFactory {- mapperInterface: ClassT- methodCache: MapMethod, MapperMethod-- newInstance(SqlSession sqlSession): T# newInstance(MapperProxyT mapperProxy): T}class MapperProxy {-- invoke(Object proxy, Method method, Object[] args): Object}class MapperMethod {-- execute(SqlSession sqlSession, Object[] args): Object}MapperProxyFactory .. MapperProxy: new MapperProxy()MapperProxy .. MapperMethod: mapperMethod.execute() }namespace org.apache.ibatis.executor #EEE {interface Executor {-- update(MappedStatement ms, Object parameter): int query(MappedStatement ms, \nObject parameter, \nRowBounds rowBounds, \nResultHandler resultHandler, \nCacheKey cacheKey, \nBoundSql boundSql): ListE commit(boolean required): void rollback(boolean required): void getTransaction(): Transaction close(boolean forceRollback): void}org.apache.ibatis.binding.MapperMethod -- Executor}namespace org.apache.ibatis.plugin #EEE {interface Interceptor {-- intercept(Invocation invocation): Object plugin(Object target): Object setProperties(Properties properties): void}class Plugin {- target: Object- interceptor: Interceptor- signatureMap: MapClass?, SetMethod-- Override invoke(Object proxy, Method method, Object[] args): Object}javax.lang.reflect.InvocationHandler |-- PluginPlugin . Interceptor: Plugin.wrap }namespace org.apache.ibatis.transaction #EEE {interface Transaction {-- getConnection(): Connection commit(): void rollback(): void close(): void}interface TransactionFactory {-- newTransaction(Connection conn): Transaction newTransaction(DataSource dataSource, \n TransactionIsolationLevel level, boolean autoCommit): Transaction}javax.sql.Connection .. Transaction: getConnection()Transaction .. TransactionFactory: newTransaction() }namespace org.apache.ibatis.mapping #EEE {class Environment {- id: String- transactionFactory: TransactionFactory- dataSource: DataSource}interface DatabaseIdProvider {--setProperties(Properties p): voidgetDatabaseId(DataSource dataSource): String}class VendorDatabaseIdProvider {-- Override setProperties(Properties p): void Override getDatabaseId(DataSource dataSource): String- getDatabaseName(DataSource dataSource): String}DatabaseIdProvider |.. VendorDatabaseIdProvider }mybatis namespace org.mybatis #EEE {class SqlSessionFactoryBean {- configLocation: Resource- configuration: Configuration- mapperLocations: Resource[]- dataSource: DataSource- transactionFactory: TransactionFactory- sqlSessionFactoryBuilder: SqlSessionFactoryBuilder- sqlSessionFactory: SqlSessionFactory- plugins: Interceptor[]- databaseIdProvider: DatabaseIdProvider-- Override afterPropertiesSet(): void Override getObject(): SqlSessionFactory Override onApplicationEvent(ApplicationEvent event): void}note left of SqlSessionFactoryBean入口核心this.sqlSessionFactory buildSqlSessionFactory()end noteorg.springframework.beans.factory.FactoryBean |.. SqlSessionFactoryBeanorg.springframework.beans.factory.InitializingBean |.. SqlSessionFactoryBeanorg.springframework.context.ApplicationListener |.. SqlSessionFactoryBean }enduml写在后面 如果本文内容对您有价值或者有启发的话欢迎点赞、关注、评论和转发。您的反馈和陪伴将促进我们共同进步和成长。 系列文章 【UML】- 类图 【GitHub】- design-pattern设计模式 【连接池】-从源码到适配上你遇到过数据库连接池的问题吗This connection has been closed 【连接池】-从源码到适配下使用dynamic-datasource导致连接池没生效升级版本
http://www.zqtcl.cn/news/642919/

相关文章:

  • 苏州高端网站设计制作wordpress改固定连接
  • 门户网站开源sae安装wordpress
  • 建设彩票网站需要哪些要求城乡与住房建设厅网站首页
  • 公司做网站费用计入什么科目网络建设规划
  • 外贸网站建设案例深圳设计网站培训
  • 龙岗地区做网站公司北京装饰公司排行 2019
  • 大企业网站建设方案wordpress博客模板查询
  • 手机网站建设动态公司做网站效果怎么样
  • 网站推广和优化教程上海网络科技有限公司招聘
  • 即墨建网站价格商城二次开发
  • 网站排名易下拉教程怎么做网店运营
  • 聊城做网站公司聊城博达海外服务器租用多少钱一年
  • 手机上网站做国外销售都上什么网站
  • 网站建设与管理报告书做电销有什么资料网站
  • 网站建设哪家最好企业商城网站建设方案
  • 舟山市建设工程质量监督站网站网页版微信二维码加载失败
  • 金融网站html5模板给自己家的公司做网站好做吗
  • 新农村建设投诉在哪个网站上海做电缆桥架的公司网站
  • 免费行情100个软件网络优化论文
  • asp.net动态的网站开发个人业务网站带后台
  • 控制网站的大量访问关于实验室建设的英文网站
  • 中国容桂品牌网站建设怎么自己做个网站做链接跳转
  • 安徽省建设工程协会网站昆明官网seo厂家
  • 品牌整合推广搜狗优化好的网站
  • 娄底手机网站制作深圳网站建设怎么做
  • 好的龙岗网站建设附近装修公司电话和地址
  • 网站后台生成文章很慢网络营销毕业设计
  • 如何把资料上传到网站什么叫高端网站定制
  • 郑州企业网站建设团队什么是交换链接
  • 如何建立一个外贸公司网站活动营销的方式有哪些