国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - MyBatis Plus插件機制與執行流程原理分析詳解

MyBatis Plus插件機制與執行流程原理分析詳解

2020-09-10 00:53mrchaochao Java教程

這篇文章主要介紹了MyBatis Plus插件機制與執行流程原理分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

MyBatis Plus插件

MyBatis Plus提供了分頁插件PaginationInterceptor、執行分析插件SqlExplainInterceptor、性能分析插件PerformanceInterceptor以及樂觀鎖插件OptimisticLockerInterceptor。

Mybatis 通過插件 (Interceptor) 可以做到攔截四大對象相關方法的執行 ,根據需求完成相關數據的動態改變。

四大對象是:

  • Executor
  • StatementHandler
  • ParameterHandler
  • ResultSetHandler

四大對象的每個對象在創建時,都會執行interceptorChain.pluginAll(),會經過每個插件對象的 plugin()方法,目的是為當前的四大對象創建代理。代理對象就可以攔截到四大對象相關方法的執行,因為要執行四大對象的方法需要經過代理 。

① xml下插件的配置

如下所示:

<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 數據源 -->
<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>
<!-- 插件注冊 --><property name="plugins"><list><!-- 注冊分頁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor">
</bean>
<!-- 注冊執行分析插件 --><bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property></bean>
<!-- 注冊性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"><property name="format" value="true">
</property>
<!-- <property name="maxTime" value="5"></property> --></bean>
<!-- 注冊樂觀鎖插件 -->
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor"></bean>
</list></property></bean>

② springboot下注冊插件

這里以分頁插件為例:

@Bean public PaginationInterceptor paginationInterceptor() 
{  
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();  
// 設置請求的頁面大于最大頁后操作, true調回到首頁,false 繼續請求 默認false  
// paginationInterceptor.setOverflow(false); 
// 設置最大單頁限制數量,默認 500 條,-1 不受限制  
// paginationInterceptor.setLimit(500); 
// 開啟 count 的 join 優化,只針對部分 left join  
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); 
return paginationInterceptor; 
}

③ SqlExplainInterceptor

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

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

在插件的底層通過SQL語句分析命令 Explain 分析當前的 SQL語句,根據結果集中的 Extra列來斷定當前是否全表操作。

④ 性能分析插件

性能分析攔截器,全類名是com.baomidou.mybatisplus.plugins.PerformanceInterceptor,用于輸出每條 SQL 語句及其執行時間。SQL性能執行分析 ,開發環境使用 超過指定時間,停止運行。

⑤ 樂觀鎖插件

全類名是com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor。如果想實現如下需求 : 當要更新一條記錄的時候,希望這條記錄沒有被別人更新,就可以使用該插件進行判斷。

樂觀鎖的實現原理(@Version 用于注解實體字段,必須要有) :

  • 取出記錄時,獲取當前 version
  • 更新時,帶上這個version
  • 執行更新時,set version = yourVersion+1 where version = yourVersion
  • 如果 version不對,就更新失敗

【2】獲取sqlSessionFactoryBean

如下圖所示,在系統啟動時會初始化定義的bean。DefaultListableBeanFactory.preInstantiateSingletons方法中會從beanDefinitionNames中獲取bean name然后依次創建。

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

MyBatis Plus插件機制與執行流程原理分析詳解

① 獲取bean的過程中bean屬性

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

MyBatis Plus插件機制與執行流程原理分析詳解

② createBean

第一次獲取bean的時候會走到AbstractAutowireCapableBeanFactory.createBean進行bean的創建。

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

在AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation中就會分別執行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;
}

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

MyBatis Plus插件機制與執行流程原理分析詳解

③ doCreateBean

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

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException 
{
// Instantiate the bean.--實例化beanBeanWrapper instanceWrapper = null;if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) 
{//獲取bean的包裝對象-這里很重要 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 {//調用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; }}//...//這里暫時忽略其他代碼
// Initialize the bean instance.--初始化bean實例Object exposedObject = bean;try {//如下方法很重要 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) 
{ 
 exposedObject = initializeBean(beanName, exposedObject, mbd); 
}}//...

④ populateBean

顧名思義,為bean實例屬性賦值。

AbstractAutowireCapableBeanFactory.populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {//獲取屬性值列表PropertyValues pvs = mbd.getPropertyValues();
//...該種符號表示暫時忽略其他代碼
//在為bean屬性賦值前,給InstantiationAwareBeanPostProcessors 機會修改bean的狀態//應用場景如支持字段注入boolean continueWithPropertyPopulation = true;
//循環調用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注解字段,進行主動注入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);//循環調用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); }}//在這里為屬性賦值,會進行類型轉換,這里注意關鍵詞deep copy//如果是引用類型且bean沒有存在,則會進行bean的創建過程applyPropertyValues(beanName, mbd, bw, pvs);}

如下圖所示在創建sqlSessionFactoryBean過程中會創建其屬性globalConfiguration對象:

MyBatis Plus插件機制與執行流程原理分析詳解


如下圖所示在創建sqlSessionFactoryBean過程中(從左側的方法順序就可以看出來)會創建其屬性PaginationInterceptor對象:

MyBatis Plus插件機制與執行流程原理分析詳解


如下圖所示在創建sqlSessionFactoryBean過程中(從左側的方法順序就可以看出來)會創建其屬性SqlExplainInterceptor對象:

MyBatis Plus插件機制與執行流程原理分析詳解


如下圖所示在創建sqlSessionFactoryBean過程中(從左側的方法順序就可以看出來)會創建其屬性PerformanceInterceptor對象:

MyBatis Plus插件機制與執行流程原理分析詳解


如下圖所示在創建sqlSessionFactoryBean過程中(從左側的方法順序就可以看出來)會創建其屬性OptimisticLockerInterceptor對象:

MyBatis Plus插件機制與執行流程原理分析詳解


⑤ 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 { //調用意識/通知方法 invokeAwareMethods(beanName, bean); 
}
 Object wrappedBean = bean; 
 if (mbd == null || !mbd.isSynthetic())
 { //調用bean后置處理器的前置方法 
 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 
 } //調用初始化方法 
 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 + "'"); 
 } 
 //調用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(); 
 } }//調用自定義初始化方法 if (mbd != null)
 { 
 String initMethodName = mbd.getInitMethodName(); 
 if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  
 !mbd.isExternallyManagedInitMethod(initMethodName))
 {  
 invokeCustomInitMethod(beanName, bean, mbd); 
 } 
 }}

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

MyBatis Plus插件機制與執行流程原理分析詳解

⑥ MybatisSqlSessionFactoryBean.afterPropertiesSet

如下所示,代碼很簡短只是創建了sqlSessionFactory。

@Overridepublic void afterPropertiesSet() throws Exception
{ 
notNull(dataSource, "Property 'dataSource' is required"); //sqlSessionFactoryBuilder在populateBean的applyPropertyValues過程中已經存在! 
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();
 }

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

MyBatis Plus插件機制與執行流程原理分析詳解

我們看一下sqlSessionFactory,這是一段很長的過程:

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會從這里創建MybatisXMLConfigBuilder, //其構造方法又創建了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));  
 }  
 }  // 取得類型轉換注冊器  
 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)); 
 // 設置元數據相關 
 GlobalConfigUtils.setMetaData(dataSource, globalConfig); SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(configuration); 
 // TODO SqlRunner 
 SqlRunner.FACTORY = sqlSessionFactory; // TODO 緩存 sqlSessionFactory globalConfig.setSqlSessionFactory(sqlSessionFactory); // TODO 設置全局參數屬性 
 globalConfig.signGlobalConfig(sqlSessionFactory); 
 if (!isEmpty(this.mapperLocations)) {  
 if (globalConfig.isRefresh()) {   
 //TODO 設置自動刷新配置 減少配置   
 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對象
  • 獲取Configuration對象-MybatisConfiguration
  • 配置對象Configuration添加插件configuration.addInterceptor(plugin);
  • xmlConfigBuilder.parse()對configuration做進一步處理
  • 獲取SpringManagedTransactionFactory用來創建SpringManagedTransaction
  • 獲取一個DefaultSqlSessionFactory實例對象
  • globalConfig.setSqlSessionFactory(sqlSessionFactory)中會創建MybatisSqlSessionTemplate
  • 解析mapperLocation對應的一個個mapper配置文件,使用助手builderAssistant的addMappedStatement方法將一個個結點添加配置對象中
  • 其他屬性設置等等

也就是說,在MybatisSqlSessionFactoryBean.afterPropertiesSet方法執行結束后,SqlSessionFactory、SqlSessionTemplate、Configuration等都已存在!

【3】查詢執行流程分析

示例代碼如下:

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

如下圖所示,此時我們獲取到的employeeMapper其實是個代理對象:

MyBatis Plus插件機制與執行流程原理分析詳解

MyBatis Plus插件機制與執行流程原理分析詳解

總結

到此這篇關于MyBatis Plus插件機制與執行流程原理分析的文章就介紹到這了,更多相關MyBatis Plus插件機制內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/mrchaochao/article/details/108493070

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 成人网视频在线观看 | 成人av电影网址 | 欧美日韩精品在线 | 精久久| 99久久久国产精品 | 毛片国产 | 性毛片| 免费国产wwwwwww网站 | 国产成人一区二区三区 | 蜜桃av噜噜一区二区三区小说 | 成人在线观看av | 中文字幕视频二区 | 精品三级| av片网站| 亚洲小视频 | 免费一区二区三区 | 久久成人免费视频 | 亚洲福利| 精品无码久久久久久久动漫 | 亚洲精品二区三区 | 羞羞视频免费观看网站 | 91在线电影 | 91在线高清观看 | 91在线视频播放 | 亚洲激情视频 | 欧美天天 | 日韩欧美视频 | 亚洲视频综合 | 亚洲精品一区二区网址 | 字幕网av | 国产综合亚洲精品一区二 | 欧美日韩a| 国产精品一区二区无线 | 日韩成人在线播放 | 自拍偷拍视频网站 | 欧美成人a∨高清免费观看 亚洲国产精品尤物yw在线观看 | 成年人毛片在线观看 | 免费观看a级毛片在线播放 成人片免费看 | 国产高清在线精品一区二区三区 | 亚洲一区二区视频 | 国产一区二区三区免费播放 |