MyBatis底层基础和拦截器看一个例子SimpleMyBatis2020/6/17第一遍从头到尾简单过一遍代码看看代码中的简单注释了解MyBatis内部如何使用这些对象2020/6/17第二遍我们对照XML来看这段代码了解这些XML和对象之间的关系2020/6/17代码和XML对照-Configuration//创建配置文件finalConfigurationconfig=newConfiguration();config.setCacheEnabled(true);config.setLazyLoadingEnabled(false);config.setAggressiveLazyLoading(true);settingssettingname=cacheEnabledvalue=true/settingname=lazyLoadingEnabledvalue=false/settingname=aggressiveLazyLoadingvalue=true//settings2020/6/17代码和XML对照-拦截器//为了后续说明拦截器,这里添加两个简单例子config.addInterceptor(newSampleExecutorInterceptor());config.addInterceptor(newSampleResultSetHandlerInterceptor());plugins!--包名太长,省略包名为xxx--plugininterceptor=xxx.SampleExecutorInterceptor/plugininterceptor=xxx.SampleResultSetHandlerInterceptor//plugins2020/6/17代码和XML对照-Environment//创建DataSourcePropertiesprops=Resources.getResourceAsProperties(jdbc.properties);UnpooledDataSourcedataSource=newUnpooledDataSource();dataSource.setDriver(props.getProperty(driver));dataSource.setUrl(props.getProperty(url));dataSource.setUsername(props.getProperty(username));dataSource.setPassword(props.getProperty(password));Transactiontransaction=newJdbcTransaction(dataSource,null,false);finalExecutorexecutor=config.newExecutor(transaction);environmentsdefault=developmentenvironmentid=developmenttransactionManagertype=JDBC/dataSourcetype=UNPOOLEDpropertyname=drivervalue=com.mysql.jdbc.Driver/propertyname=urlvalue=jdbc:mysql://localhost:3306/pagehelper/propertyname=usernamevalue=pagehelper/propertyname=passwordvalue=pagehelper//dataSource/environment/environments2020/6/17代码和XML对照-CachefinalCachecountryCache=newSynchronizedCache(//同步缓存newSerializedCache(//序列化缓存newLoggingCache(//日志缓存newLruCache(//最少使用缓存newPerpetualCache(country_cache)//持久缓存))));msBuilder.cache(countryCache);//相当于将cache/添加到xml的方法上cache/cache/就是这么复杂的一个对象,我们在cache/中可以配置属性是type和eviction,对应上面代码中PerpetualCache和LruCache,当type不变的时候,就是上面的这个结构,eviction可以修改LruCache这一层,当type修改的时候,整个对象就是你type设置的这一层缓存对象,不会有这么复杂的结构。修饰模式:修饰模式2020/6/17代码和XML对照-selectselectid=selectAllresultType=CountryresultMap=defaultResultMapSELECT*FROMcountryWHEREid=#{id}/select这样的一个select(或insert、update、delete)对应的就是一个MappedStatement,这个对象比较复杂,由很多对象组合而成。其中resultType和resultMap对应了ResultMap对象#{id}会产生ParameterMapping中间的SQL会产生一个合适的SqlSource对象2020/6/17代码和XML对照-resultMapresultMapid=defaultResultMaptype=xxx.Countryidcolumn=idproperty=idjavaType=int/resultcolumn=countrynameproperty=countrynamejavaType=String/resultcolumn=countrycodeproperty=countrycodejavaType=String//resultMapfinalResultMapresultMap=newResultMap.Builder(config,defaultResultMap,Country.class,newArrayListResultMapping(){{//默认都是普通的result,有个flags属性可以设置为idadd(newResultMapping.Builder(config,id,id,int.class).build());add(newResultMapping.Builder(config,countryname,countryname,String.class).build());add(newResultMapping.Builder(config,countrycode,countrycode,registry.getTypeHandler(String.class)).build());}}).build();2020/6/17代码和XML对照-resultTypefinalResultMapresultMap=newResultMap.Builder(config,defaultResultMap,Country.class,newArrayListResultMapping()).build();resultMapid=defaultResultMaptype=xxx.Country/resultMapselect...resultType=xxx.Country...2020/6/17resultMap和resultTypeListResultMapresultMaps=newArrayListResultMap();resultMaps.add(resultMap);//设置返回值的resultMapmsBuilder.resultMaps(resultMaps);2020/6/17代码和XML对照-SqlSourceStaticSqlSourcesqlSource=newStaticSqlSource(config,SELECT*FROMcountryWHEREid=?);selectid=selectAllresultType=CountryresultMap=defaultResultMapSELECT*FROMcountryWHEREid=#{id}/select2020/6/17参数映射-ParameterMap//由于上面的SQL有个参数id,这里需要提供ParameterMapping(参数映射)ListParameterMappingparameterMappings=newArrayListParameterMapping();//通过ParameterMapping.Builder创建ParameterMappingparameterMappings.add(newParameterMapping.Builder(config,id,registry.getTypeHandler(int.class)).build());//通过ParameterMap.Builder创建ParameterMapmsBuilder.parameterMap(newParameterMap.Builder(config,defaultParameterMap,Country.class,parameterMappings).build());2020/6/17MappedStatement将前面说的这些对象组合到MappedStatement中后,就得到了ms://创建msMappedStatement.BuildermsBuilder=newMappedStatement.Builder(config,tk.mybatis.selectCountry,sqlSource,SqlCommandType.SELECT);msBuilder.parameterMap(paramBuilder.build());//设置返回值的resultMapmsBuilder.resultMaps(resultMaps);//设置缓存msBuilder.cache(countryCache);//创建msMappedStatementms=msBuilder.build();mappernamespace=tk.mybatisselectid=selectCountry...2020/6/17第三遍我们重点看(SystemMetaObject)InterceptorSqlSourceSystemMetaObject用法protectedvoidsetSqlSource(MappedStatementms,SqlSourcesqlSource){MetaObjectmsObject=SystemMetaObject.forObject(ms);msObject.setValue(sqlSource,sqlSource);//如果是Jdbc3KeyGenerator,就设置为MultipleJdbc3KeyGeneratorKeyGeneratorkeyGenerator=ms.getKeyGenerator();if(keyGeneratorinstanceofJdbc3KeyGenerator){msObject.setValue(keyGenerator,newMultipleJdbc3KeyGenerator());}}MappedStatementms=(MappedStatement)invocation.getA