欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2020年09月09日 17:22:12   作者:mrchaochao  
這篇文章主要介紹了MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

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 id="sqlSessionFactoryBean" 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í)行分析攔截器,全類(lèi)名是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)前是否全表操作。

④ 性能分析插件

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

⑤ 樂(lè)觀鎖插件

全類(lèi)名是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)行類(lèi)型轉(zhuǎn)換,這里注意關(guān)鍵詞deep copy//如果是引用類(lèi)型且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 自定義枚舉類(lèi)掃描處理 
 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));  
 }  
 }  // 取得類(lèi)型轉(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】查詢(xún)執(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)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 常用校驗(yàn)注解之@NotNull,@NotBlank,@NotEmpty的區(qū)別及說(shuō)明

    常用校驗(yàn)注解之@NotNull,@NotBlank,@NotEmpty的區(qū)別及說(shuō)明

    這篇文章主要介紹了常用校驗(yàn)注解之@NotNull,@NotBlank,@NotEmpty的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 詳細(xì)聊聊JDK中的反模式接口常量

    詳細(xì)聊聊JDK中的反模式接口常量

    這篇文章主要給大家介紹了關(guān)于JDK中反模式接口常量的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用jdk具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • SpringCloud?LoadBalancerClient?負(fù)載均衡原理解析

    SpringCloud?LoadBalancerClient?負(fù)載均衡原理解析

    LoadBalancerClient?是?SpringCloud?提供的一種負(fù)載均衡客戶端,Ribbon?負(fù)載均衡組件內(nèi)部也是集成了?LoadBalancerClient?來(lái)實(shí)現(xiàn)負(fù)載均衡,本文給大家深入解析?LoadBalancerClient?接口源碼,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • Spring cloud 限流的多種方式

    Spring cloud 限流的多種方式

    在頻繁的網(wǎng)絡(luò)請(qǐng)求時(shí),服務(wù)有時(shí)候也會(huì)受到很大的壓力,尤其是那種網(wǎng)絡(luò)攻擊,非法的。這樣的情形有時(shí)候需要作一些限制。本文主要介紹了兩種限流方法,感興趣的可以了解一下
    2021-06-06
  • java Arrays快速打印數(shù)組的數(shù)據(jù)元素列表案例

    java Arrays快速打印數(shù)組的數(shù)據(jù)元素列表案例

    這篇文章主要介紹了java Arrays快速打印數(shù)組的數(shù)據(jù)元素列表案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Java并發(fā)工具類(lèi)Phaser詳解

    Java并發(fā)工具類(lèi)Phaser詳解

    這篇文章主要介紹了Java并發(fā)工具類(lèi)Phaser詳解,Phaser(階段協(xié)同器)是一個(gè)Java實(shí)現(xiàn)的并發(fā)工具類(lèi),用于協(xié)調(diào)多個(gè)線程的執(zhí)行,它提供了一些方便的方法來(lái)管理多個(gè)階段的執(zhí)行,可以讓程序員靈活地控制線程的執(zhí)行順序和階段性的執(zhí)行,需要的朋友可以參考下
    2023-11-11
  • SpringBoot使用自動(dòng)配置xxxAutoConfiguration

    SpringBoot使用自動(dòng)配置xxxAutoConfiguration

    這篇文章介紹了SpringBoot自動(dòng)配置xxxAutoConfiguration的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • 編譯大型Java項(xiàng)目class沖突導(dǎo)致報(bào)錯(cuò)的解決方案

    編譯大型Java項(xiàng)目class沖突導(dǎo)致報(bào)錯(cuò)的解決方案

    這篇文章給大家盤(pán)點(diǎn)編譯大型項(xiàng)目class沖突導(dǎo)致報(bào)錯(cuò)的解決方案,文中通過(guò)代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-10-10
  • Java Math類(lèi)、Random類(lèi)、System類(lèi)及BigDecimal類(lèi)用法示例

    Java Math類(lèi)、Random類(lèi)、System類(lèi)及BigDecimal類(lèi)用法示例

    這篇文章主要介紹了Java Math類(lèi)、Random類(lèi)、System類(lèi)及BigDecimal類(lèi)用法,結(jié)合實(shí)例形式分析了java數(shù)值運(yùn)算相關(guān)的Math類(lèi)、Random類(lèi)、System類(lèi)及BigDecimal類(lèi)基本功能與使用技巧,需要的朋友可以參考下
    2019-03-03
  • java之swing實(shí)現(xiàn)復(fù)選框的方法

    java之swing實(shí)現(xiàn)復(fù)選框的方法

    這篇文章主要介紹了java之swing實(shí)現(xiàn)復(fù)選框的方法,實(shí)例分析了java基于圖形界面復(fù)選框的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09

最新評(píng)論