日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

瀏覽:20日期:2023-10-22 17:17:04

MyBatis Plus插件

MyBatis Plus提供了分頁(yè)插件PaginationInterceptor、執(zhí)行分析插件SqlExplainInterceptor、性能分析插件PerformanceInterceptor以及樂(lè)觀鎖插件OptimisticLockerInterceptor。

Mybatis 通過(guò)插件 (Interceptor) 可以做到攔截四大對(duì)象相關(guān)方法的執(zhí)行 ,根據(jù)需求完成相關(guān)數(shù)據(jù)的動(dòng)態(tài)改變。

四大對(duì)象是:

Executor StatementHandler ParameterHandler ResultSetHandler

四大對(duì)象的每個(gè)對(duì)象在創(chuàng)建時(shí),都會(huì)執(zhí)行interceptorChain.pluginAll(),會(huì)經(jīng)過(guò)每個(gè)插件對(duì)象的 plugin()方法,目的是為當(dāng)前的四大對(duì)象創(chuàng)建代理。代理對(duì)象就可以攔截到四大對(duì)象相關(guān)方法的執(zhí)行,因?yàn)橐獔?zhí)行四大對(duì)象的方法需要經(jīng)過(guò)代理 。

① xml下插件的配置

如下所示:

<bean class='com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean'><!-- 數(shù)據(jù)源 --><property name='dataSource' ref='dataSource'></property><property name='configLocation' value='classpath:mybatis-config.xml'></property><!-- 別名處理 --><property name='typeAliasesPackage' value='com.jane.mp.beans'></property><!-- 注入全局MP策略配置 --><property name='globalConfig' ref='globalConfiguration'></property><!-- 插件注冊(cè) --><property name='plugins'><list><!-- 注冊(cè)分頁(yè)插件 --><bean class='com.baomidou.mybatisplus.plugins.PaginationInterceptor'></bean><!-- 注冊(cè)執(zhí)行分析插件 --><bean class='com.baomidou.mybatisplus.plugins.SqlExplainInterceptor'><property name='stopProceed' value='true'></property></bean><!-- 注冊(cè)性能分析插件 --><bean class='com.baomidou.mybatisplus.plugins.PerformanceInterceptor'><property name='format' value='true'></property><!-- <property name='maxTime' value='5'></property> --></bean><!-- 注冊(cè)樂(lè)觀鎖插件 --><bean class='com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor'></bean></list></property></bean>

② springboot下注冊(cè)插件

這里以分頁(yè)插件為例:

@Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 設(shè)置請(qǐng)求的頁(yè)面大于最大頁(yè)后操作, true調(diào)回到首頁(yè),false 繼續(xù)請(qǐng)求 默認(rèn)false // paginationInterceptor.setOverflow(false); // 設(shè)置最大單頁(yè)限制數(shù)量,默認(rèn) 500 條,-1 不受限制 // paginationInterceptor.setLimit(500); // 開(kāi)啟 count 的 join 優(yōu)化,只針對(duì)部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; }

③ SqlExplainInterceptor

SQL執(zhí)行分析攔截器,全類名是com.baomidou.mybatisplus.plugins.SqlExplainInterceptor,只支持 MySQL5.6.3以上版本。

該插件的作用是分析 DELETE UPDATE語(yǔ)句 ,防止小白或者惡意進(jìn)行DELETE UPDATE全表操作,不建議在生產(chǎn)環(huán)境中使用會(huì)造成性能下降,

在插件的底層通過(guò)SQL語(yǔ)句分析命令 Explain 分析當(dāng)前的 SQL語(yǔ)句,根據(jù)結(jié)果集中的 Extra列來(lái)斷定當(dāng)前是否全表操作。

④ 性能分析插件

性能分析攔截器,全類名是com.baomidou.mybatisplus.plugins.PerformanceInterceptor,用于輸出每條 SQL 語(yǔ)句及其執(zhí)行時(shí)間。SQL性能執(zhí)行分析 ,開(kāi)發(fā)環(huán)境使用 超過(guò)指定時(shí)間,停止運(yùn)行。

⑤ 樂(lè)觀鎖插件

全類名是com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor。如果想實(shí)現(xiàn)如下需求 : 當(dāng)要更新一條記錄的時(shí)候,希望這條記錄沒(méi)有被別人更新,就可以使用該插件進(jìn)行判斷。

樂(lè)觀鎖的實(shí)現(xiàn)原理(@Version 用于注解實(shí)體字段,必須要有) :

取出記錄時(shí),獲取當(dāng)前 version 更新時(shí),帶上這個(gè)version 執(zhí)行更新時(shí),set version = yourVersion+1 where version = yourVersion 如果 version不對(duì),就更新失敗

【2】獲取sqlSessionFactoryBean

如下圖所示,在系統(tǒng)啟動(dòng)時(shí)會(huì)初始化定義的bean。DefaultListableBeanFactory.preInstantiateSingletons方法中會(huì)從beanDefinitionNames中獲取bean name然后依次創(chuàng)建。

這里可以看到RootBeanDefinition是com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean。

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

① 獲取bean的過(guò)程中bean屬性

如下所示,在getBean過(guò)程中可以看到bean的屬性:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

② createBean

第一次獲取bean的時(shí)候會(huì)走到AbstractAutowireCapableBeanFactory.createBean進(jìn)行bean的創(chuàng)建。

/** 創(chuàng)建一個(gè)bean實(shí)例,為bean實(shí)例設(shè)置屬性值,調(diào)用post-processors-bean后置處理器 */@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {//...暫時(shí)忽略其他代碼 try {// 這里會(huì)首先觸發(fā)BeanPostProcessors ,如果這里能獲取到bean則直接返回,不再走doCreateBean Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }//...暫時(shí)忽略其他代碼

在AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation中就會(huì)分別執(zhí)行bean后置處理器的前置和后置方法。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)){ // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()){ Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null){ bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean;}

執(zhí)行后置處理器的前置方法如下所示:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

③ doCreateBean

AbstractAutowireCapableBeanFactory.doCreateBean是創(chuàng)建bean的核心方法,這會(huì)為bean屬性賦值并會(huì)觸發(fā)bean后置處理器、InitializingBean以及自定init方法等。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {// Instantiate the bean.--實(shí)例化beanBeanWrapper instanceWrapper = null;if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//獲取bean的包裝對(duì)象-這里很重要 instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);mbd.resolvedTargetType = beanType;// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try {//調(diào)用MergedBeanDefinitionPostProcessors的postProcessMergedBeanDefinition方法 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, 'Post-processing of merged bean definition failed', ex); } mbd.postProcessed = true; }}//...//這里暫時(shí)忽略其他代碼// Initialize the bean instance.--初始化bean實(shí)例Object exposedObject = bean;try {//如下方法很重要 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); }}//...

④ populateBean

顧名思義,為bean實(shí)例屬性賦值。

AbstractAutowireCapableBeanFactory.populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {//獲取屬性值列表PropertyValues pvs = mbd.getPropertyValues();//...該種符號(hào)表示暫時(shí)忽略其他代碼//在為bean屬性賦值前,給InstantiationAwareBeanPostProcessors 機(jī)會(huì)修改bean的狀態(tài)//應(yīng)用場(chǎng)景如支持字段注入boolean continueWithPropertyPopulation = true;//循環(huán)調(diào)用InstantiationAwareBeanPostProcessors 的postProcessAfterInstantiation方法if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } }}if (!continueWithPropertyPopulation) { return;}//解析autowire注解字段,進(jìn)行主動(dòng)注入if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);//循環(huán)調(diào)用InstantiationAwareBeanPostProcessors 的postProcessPropertyValues方法if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }}//在這里為屬性賦值,會(huì)進(jìn)行類型轉(zhuǎn)換,這里注意關(guān)鍵詞deep copy//如果是引用類型且bean沒(méi)有存在,則會(huì)進(jìn)行bean的創(chuàng)建過(guò)程applyPropertyValues(beanName, mbd, bw, pvs);}

如下圖所示在創(chuàng)建sqlSessionFactoryBean過(guò)程中會(huì)創(chuàng)建其屬性globalConfiguration對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

如下圖所示在創(chuàng)建sqlSessionFactoryBean過(guò)程中(從左側(cè)的方法順序就可以看出來(lái))會(huì)創(chuàng)建其屬性PaginationInterceptor對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

如下圖所示在創(chuàng)建sqlSessionFactoryBean過(guò)程中(從左側(cè)的方法順序就可以看出來(lái))會(huì)創(chuàng)建其屬性SqlExplainInterceptor對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

如下圖所示在創(chuàng)建sqlSessionFactoryBean過(guò)程中(從左側(cè)的方法順序就可以看出來(lái))會(huì)創(chuàng)建其屬性PerformanceInterceptor對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

如下圖所示在創(chuàng)建sqlSessionFactoryBean過(guò)程中(從左側(cè)的方法順序就可以看出來(lái))會(huì)創(chuàng)建其屬性O(shè)ptimisticLockerInterceptor對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

⑤ initializeBean

AbstractAutowireCapableBeanFactory.initializeBean源碼如下:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd){ if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { //調(diào)用意識(shí)/通知方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //調(diào)用bean后置處理器的前置方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } //調(diào)用初始化方法 try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, 'Invocation of init method failed', ex); }

AbstractAutowireCapableBeanFactory.invokeInitMethods方法源碼如下:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod('afterPropertiesSet'))) { if (logger.isDebugEnabled()) { logger.debug('Invoking afterPropertiesSet() on bean with name ’' + beanName + '’'); } //調(diào)用InitializingBean.afterPropertiesSet if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } }//調(diào)用自定義初始化方法 if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && 'afterPropertiesSet'.equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } }}

如下圖所示,MybatisSqlSessionFactoryBean同樣實(shí)現(xiàn)了InitializingBean接口。那么我們就需要注意其afterPropertiesSet方法了。

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

⑥ MybatisSqlSessionFactoryBean.afterPropertiesSet

如下所示,代碼很簡(jiǎn)短只是創(chuàng)建了sqlSessionFactory。

@Overridepublic void afterPropertiesSet() throws Exception{ notNull(dataSource, 'Property ’dataSource’ is required'); //sqlSessionFactoryBuilder在populateBean的applyPropertyValues過(guò)程中已經(jīng)存在! notNull(sqlSessionFactoryBuilder, 'Property ’sqlSessionFactoryBuilder’ is required'); state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null), 'Property ’configuration’ and ’configLocation’ can not specified with together'); this.sqlSessionFactory = buildSqlSessionFactory(); }

進(jìn)入afterPropertiesSet()方法前MybatisSqlSessionFactoryBean如下所示:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

我們看一下sqlSessionFactory,這是一段很長(zhǎng)的過(guò)程:

protected SqlSessionFactory buildSqlSessionFactory() throws Exception{ Configuration configuration; // TODO 加載自定義 MybatisXmlConfigBuilder MybatisXMLConfigBuilder xmlConfigBuilder = null; if (this.configuration != null) { configuration = this.configuration; if (configuration.getVariables() == null) { configuration.setVariables(this.configurationProperties); } else if (this.configurationProperties != null) { configuration.getVariables().putAll(this.configurationProperties); } } else if (this.configLocation != null) { //通常如果配置了configLocation會(huì)從這里創(chuàng)建MybatisXMLConfigBuilder, //其構(gòu)造方法又創(chuàng)建了MybatisConfiguration xmlConfigBuilder = new MybatisXMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); configuration = xmlConfigBuilder.getConfiguration(); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug('Property ’configuration’ or ’configLocation’ not specified, using default MyBatis Configuration'); } // TODO 使用自定義配置 configuration = new MybatisConfiguration(); if (this.configurationProperties != null) { configuration.setVariables(this.configurationProperties); } } if (this.objectFactory != null) { configuration.setObjectFactory(this.objectFactory); } if (this.objectWrapperFactory != null) { configuration.setObjectWrapperFactory(this.objectWrapperFactory); } if (this.vfs != null) { configuration.setVfsImpl(this.vfs); } if (hasLength(this.typeAliasesPackage)) { // TODO 支持自定義通配符 String[] typeAliasPackageArray; if (typeAliasesPackage.contains('*') && !typeAliasesPackage.contains(',') && !typeAliasesPackage.contains(';')) { typeAliasPackageArray = PackageHelper.convertTypeAliasesPackage(typeAliasesPackage); } else { typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); } if (typeAliasPackageArray == null) { throw new MybatisPlusException('not find typeAliasesPackage:' + typeAliasesPackage); } for (String packageToScan : typeAliasPackageArray) { configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Scanned package: ’' + packageToScan + '’ for aliases'); } } } // TODO 自定義枚舉類掃描處理 if (hasLength(this.typeEnumsPackage)) { Set<Class> classes = null; if (typeEnumsPackage.contains('*') && !typeEnumsPackage.contains(',') && !typeEnumsPackage.contains(';')) { classes = PackageHelper.scanTypePackage(typeEnumsPackage); } else { String[] typeEnumsPackageArray = tokenizeToStringArray(this.typeEnumsPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); if (typeEnumsPackageArray == null) { throw new MybatisPlusException('not find typeEnumsPackage:' + typeEnumsPackage); } classes = new HashSet<Class>(); for (String typePackage : typeEnumsPackageArray) { classes.addAll(PackageHelper.scanTypePackage(typePackage)); } } // 取得類型轉(zhuǎn)換注冊(cè)器 TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); for (Class cls : classes) { if (cls.isEnum()) { if (IEnum.class.isAssignableFrom(cls)) { typeHandlerRegistry.register(cls.getName(), com.baomidou.mybatisplus.handlers.EnumTypeHandler.class.getCanonicalName()); } else { // 使用原生 EnumOrdinalTypeHandler typeHandlerRegistry.register(cls.getName(), org.apache.ibatis.type.EnumOrdinalTypeHandler.class.getCanonicalName()); } } } } if (!isEmpty(this.typeAliases)) { for (Class<?> typeAlias : this.typeAliases) { configuration.getTypeAliasRegistry().registerAlias(typeAlias); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Registered type alias: ’' + typeAlias + '’'); } } } if (!isEmpty(this.plugins)) { for (Interceptor plugin : this.plugins) { configuration.addInterceptor(plugin); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Registered plugin: ’' + plugin + '’'); } } } if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray){ configuration.getTypeHandlerRegistry().register(packageToScan); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Scanned package: ’' + packageToScan + '’ for type handlers'); } } } if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Registered type handler: ’' + typeHandler + '’'); } } } if (this.databaseIdProvider != null) {//fix #64 set databaseId before parse mapper xmls try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException('Failed getting a databaseId', e); } } if (this.cache != null) { configuration.addCache(this.cache); } if (xmlConfigBuilder != null) { try { xmlConfigBuilder.parse(); if (LOGGER.isDebugEnabled()) { LOGGER.debug('Parsed configuration file: ’' + this.configLocation + '’'); } } catch (Exception ex) { throw new NestedIOException('Failed to parse config resource: ' + this.configLocation, ex); } finally { ErrorContext.instance().reset(); } } if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource)); // 設(shè)置元數(shù)據(jù)相關(guān) GlobalConfigUtils.setMetaData(dataSource, globalConfig); SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(configuration); // TODO SqlRunner SqlRunner.FACTORY = sqlSessionFactory; // TODO 緩存 sqlSessionFactory globalConfig.setSqlSessionFactory(sqlSessionFactory); // TODO 設(shè)置全局參數(shù)屬性 globalConfig.signGlobalConfig(sqlSessionFactory); if (!isEmpty(this.mapperLocations)) { if (globalConfig.isRefresh()) { //TODO 設(shè)置自動(dòng)刷新配置 減少配置 new MybatisMapperRefresh(this.mapperLocations, sqlSessionFactory, 2, 2, true); } for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { // TODO 這里也換了噢噢噢噢 XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException('Failed to parse mapping resource: ’' + mapperLocation + '’', e); } finally { ErrorContext.instance().reset(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug('Parsed mapper file: ’' + mapperLocation + '’'); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug('Property ’mapperLocations’ was not specified or no matching resources found'); } } return sqlSessionFactory; }

上面代碼主要做了如下事情:

獲取MybatisXMLConfigBuilder對(duì)象 獲取Configuration對(duì)象-MybatisConfiguration 配置對(duì)象Configuration添加插件configuration.addInterceptor(plugin); xmlConfigBuilder.parse()對(duì)configuration做進(jìn)一步處理 獲取SpringManagedTransactionFactory用來(lái)創(chuàng)建SpringManagedTransaction 獲取一個(gè)DefaultSqlSessionFactory實(shí)例對(duì)象 globalConfig.setSqlSessionFactory(sqlSessionFactory)中會(huì)創(chuàng)建MybatisSqlSessionTemplate 解析mapperLocation對(duì)應(yīng)的一個(gè)個(gè)mapper配置文件,使用助手builderAssistant的addMappedStatement方法將一個(gè)個(gè)結(jié)點(diǎn)添加配置對(duì)象中 其他屬性設(shè)置等等

也就是說(shuō),在MybatisSqlSessionFactoryBean.afterPropertiesSet方法執(zhí)行結(jié)束后,SqlSessionFactory、SqlSessionTemplate、Configuration等都已存在!

【3】查詢執(zhí)行流程分析

示例代碼如下:

List<Employee > emps = employeeMapper.selectPage(page, null);

如下圖所示,此時(shí)我們獲取到的employeeMapper其實(shí)是個(gè)代理對(duì)象:

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

總結(jié)

到此這篇關(guān)于MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析的文章就介紹到這了,更多相關(guān)MyBatis Plus插件機(jī)制內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
视频一区在线播放| 亚洲一区有码| 欧产日产国产精品视频| 久久精品亚洲人成影院| 亚洲激情五月| 蜜桃av一区二区| 日韩精品欧美精品| 国产精品欧美大片| 五月激情久久| 免费久久99精品国产自在现线| 亚洲开心激情| 欧美中文高清| 婷婷激情一区| 亚洲91网站| 国产+成+人+亚洲欧洲在线| 亚洲手机在线| 日韩一区欧美二区| 麻豆精品av| 欧美日韩国产高清| 欧美久久一区二区三区| www.com.cn成人| 老牛影视一区二区三区| 国产日本亚洲| 免费污视频在线一区| 亚洲精品免费观看| 精品国产亚洲一区二区三区大结局 | 久久高清免费观看| 亚洲一区欧美| 欧美精品二区| 免费不卡中文字幕在线| 国产伦一区二区三区| 久久人人88| 青草久久视频| 日本欧美不卡| 欧美日韩 国产精品| 日韩精品一卡| 欧美久久一区二区三区| 亚洲午夜电影| 免费一级欧美片在线观看网站| 伊人久久成人| 久久亚州av| 日韩精品一二三区| 国产在线看片免费视频在线观看| 欧美综合二区| 精品理论电影在线| 亚洲一二三区视频| 亚洲深夜视频| 日本精品另类| 九一国产精品| 久久精品国产免费| 中文不卡在线| 99精品在线观看| 国产精品玖玖玖在线资源| 亚洲在线观看| 日本不卡免费高清视频在线| 日本少妇精品亚洲第一区| 精品一区毛片| 亚洲欧洲美洲av| 国产欧美一区二区色老头| 妖精视频成人观看www| 日本久久黄色| 日本成人手机在线| 亚洲一区激情| 成人羞羞在线观看网站| 欧美自拍一区| 亚洲欧美成人综合| 日韩不卡在线| 国产一区二区三区四区五区 | 亚洲欧美久久久| 精品日韩视频| 精品国产三区在线| 久久国产精品免费一区二区三区| 欧美91精品| 亚洲啊v在线| 精品久久亚洲| 美女国产一区二区三区| 日韩高清电影免费| 久久午夜精品| 亚洲激情黄色| 999久久久国产精品| 成人国产精品久久| 国产精品1区在线| 91精品美女| 日韩国产欧美视频| 日韩一区二区三区在线看| 国产精品普通话对白| 日韩精品网站| 91中文字幕精品永久在线| 国产精品欧美大片| 国产调教一区二区三区| 日本天堂一区| 国产情侣一区| 久久av电影| 国产精品一线天粉嫩av| 国产亚洲观看| 免费在线观看一区| 麻豆久久一区| 国产v日韩v欧美v| bbw在线视频| 久久蜜桃精品| 2023国产精品久久久精品双| 99精品美女| 久久免费高清| 亚洲天堂免费电影| 亚洲精品**中文毛片| 亚洲日本网址| av资源亚洲| 欧美肉体xxxx裸体137大胆| 成人在线免费观看网站| 久久精品99国产精品日本| 蜜桃视频第一区免费观看| 在线视频观看日韩| 国语精品一区| 国产精品美女午夜爽爽| 国产一级成人av| 国产日韩欧美三级| 91精品在线免费视频| 亚洲免费资源| 日本 国产 欧美色综合| 自拍日韩欧美| 亚洲黄页一区| 国产亚洲福利| 亚洲欧美日韩国产综合精品二区 | 久久精品一本| 久久精品国产福利| 成人污污视频| av在线资源| 亚洲成人精品| 性欧美69xoxoxoxo| 国产亚洲精品v| 亚洲欧美不卡| 午夜亚洲福利| 日韩动漫一区| 国产精品久久久久久妇女| 国产精品mm| 日韩成人a**站| 伊人精品一区| 每日更新成人在线视频| 美女91精品| 日韩精品视频在线看| 国产亚洲一区| 美女精品久久| 福利一区视频| 欧美日韩少妇| 亚洲九九精品| 日本va欧美va精品发布| 欧美一区影院| 高清久久精品| 国产精品7m凸凹视频分类| 亚洲人妖在线| 国产情侣一区| 久久久久久久欧美精品| 精品国产精品国产偷麻豆| 国产资源在线观看入口av| 91精品亚洲| 在线国产一区二区| 亚洲1区在线| 久久一区欧美| 91精品推荐| 99国产精品久久久久久久成人热| 伊人久久亚洲| 亚洲一区二区三区四区五区午夜| 欧美色综合网| 91亚洲国产| 国产精品视区| 国产精品日本一区二区不卡视频| 日韩88av| 9国产精品视频| 美腿丝袜在线亚洲一区| 久久久噜噜噜| 亚洲涩涩av| 精品一区视频| 黄色成人91| 国产免费av一区二区三区| 激情综合网五月| 97久久亚洲| 日韩精品专区| 天堂久久一区| 日韩一区二区在线免费| 午夜视频精品| 国产精品亚洲欧美日韩一区在线| 美女久久久久久| 亚洲欧美久久精品| a国产在线视频| 亚洲aa在线| 精品网站aaa| 国产婷婷精品| 国产精品久久久久av蜜臀| 日韩中文字幕91| 国产一区二区三区四区| 首页国产欧美久久| 黄色aa久久| 日韩超碰人人爽人人做人人添| 日韩欧美不卡| 清纯唯美亚洲综合一区| 一区二区小说| 欧美精品成人| 在线 亚洲欧美在线综合一区| 日韩一区二区三区精品| 国产一区日韩一区|