在上一篇中我知道拦截器的入口在InterceptorChain中的putAll,
由putAll方法生成对象的代理,由代理的对象执行对象的方法。
因此只要得到InterceptorChain对象,则一切就可以解决了。
Configuration没有提供interceptorChain属性的get方法。
因此需要修改源码,为interceptorChain属性添加get方法。
方法由两种
1. 直接下载源码修改后编译
2. 在本地的项目中键包org.apache.ibatis.session
,然后在包下面建类
Configuration,把原来Configuration
类中的内容复制过去,在修改,
当本地有和源码中有相同的类名切具有相同的包的时候,优先加载本地的
Configuration类
package org.apache.ibatis.session;
/**
* @author Clinton Begin
*/
public class Configuration {
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
protected final InterceptorChain interceptorChain = new InterceptorChain();
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
protected final Map mappedStatements = new StrictMap("Mapped Statements collection");
protected final Map caches = new StrictMap("Caches collection");
protected final Map resultMaps = new StrictMap("Result Maps collection");
protected final Map parameterMaps = new StrictMap("Parameter Maps collection");
protected final Map keyGenerators = new StrictMap("Key Generators collection");
protected final Set loadedResources = new HashSet();
protected final Map sqlFragments = new StrictMap("XML fragments parsed from previous mappers");
protected final Collection incompleteStatements = new LinkedList();
protected final Collection incompleteCacheRefs = new LinkedList();
protected final Collection incompleteResultMaps = new LinkedList();
protected final Collection incompleteMethods = new LinkedList();
/*
* A map holds cache-ref relationship. The key is the namespace that
* references a cache bound to another namespace and the value is the
* namespace which the actual cache is bound to.
*/
protected final Map cacheRefMap = new HashMap();
protected Environment environment;
//setting的配置
/**
* 1.该配置影响的所有映射器中配置的缓存的全局开关。
*/
protected boolean cacheEnabled = true;
/**
* 2.延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。
*/
protected boolean lazyLoadingEnabled = false;
/**
* 3.当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。默认false
*/
protected boolean aggressiveLazyLoading;
/**
* 4. 是否允许单一语句返回多结果集(需要兼容驱动)。
*/
protected boolean multipleResultSetsEnabled = true;
/**
* 5.使用列标签代替列名。不同的驱动在这方面会有不同的表现
*/
protected boolean useColumnLabel = true;
/**
* 6.允许 JDBC 支持自动生成主键,需要驱动兼容
*/
protected boolean useGeneratedKeys;
/**
* 7.指定 MyBatis 应如何自动映射列到字段或属性。
* NONE 表示取消自动映射;
* PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。(意思就是映射文件中,对于resultMap标签,如果没有显式定义result标签,
* mybatis不会帮你把结果映射到model(pojo)上.除了id属性有具体值外,其余都没有)
* FULL 会自动映射任意复杂的结果集(无论是否嵌套)。
*/
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
/**
* 8.指定发现自动映射目标未知列(或者未知属性类型)的行为。
* NONE: 不做任何反应
* WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN)
* FAILING: 映射失败 (抛出 SqlSessionException)
*/
protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
/**
* 9. 配置默认的执行器。
* SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements);
* BATCH 执行器将重用语句并执行批量更新。
*/
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
/**
* 10.设置超时时间,它决定驱动等待数据库响应的秒数。
*/
protected Integer defaultStatementTimeout;
/**
* 11.果集获取数量(fetchSize)设置一个提示值,此参数只可以在查询设置中被覆盖。
*/
protected Integer defaultFetchSize;
/**
* 12. 允许在嵌套语句中使用分页(RowBounds)。 If allow, set the false.
*/
protected boolean safeRowBoundsEnabled;
/**
* 13.允许在嵌套语句中使用分页(ResultHandler)。 If allow, set the false.
*/
protected boolean safeResultHandlerEnabled = true;
/**
* 14.是否开启自动驼峰命名规则(camel case)映射
*/
protected boolean mapUnderscoreToCamelCase;
/**
* 15. MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
* 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
* 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。
*/
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
/**
* 16.当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型
*/
protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
/**
* 17. 指定哪个对象的方法触发一次延迟加载。
*/
protected Set lazyLoadTriggerMethods = new HashSet(Arrays.asList(new String[]{"equals", "clone", "hashCode", "toString"}));
/**
* 18. 指定动态 SQL 生成的默认语言。
*/
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
/**
* 19. 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,
* 这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。
* 注意基本类型(int、boolean等)是不能设置成 null 的。
*/
protected boolean callSettersOnNulls;
/**
* 20. 当返回行的所有列都是空时,MyBatis默认返回null。
* 当开启这个设置时,MyBatis会返回一个空实例。
* 它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始)
*/
protected boolean returnInstanceForEmptyRow;
/**
* 21.指定 MyBatis 增加到日志名称的前缀。
*/
protected String logPrefix;
/**
* 22.指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
*/
protected Class extends Log> logImpl;
/**
* 23. 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。默认JAVASSIST
* CGLIB | JAVASSIST
*/
protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL
/**
* 24.指定VFS的实现(虚拟文件系统)
*/
protected Class extends VFS> vfsImpl;
/**
* 25.允许使用方法签名中的名称作为语句参数名称。
* 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始)
*/
protected boolean useActualParamName = true;
/**26.
* Configuration factory class.
* Used to create Configuration for loading deserialized unread properties.
*
* @see Issue 300 (google code)
*/
protected Class> configurationFactory;
protected Properties variables = new Properties();
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
protected String databaseId;
public Configuration(Environment environment) {
this();
this.environment = environment;
}
public Configuration() {
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
languageRegistry.register(RawLanguageDriver.class);
}
public String getLogPrefix() {
return logPrefix;
}
public void setLogPrefix(String logPrefix) {
this.logPrefix = logPrefix;
}
public Class extends Log> getLogImpl() {
return logImpl;
}
public void setLogImpl(Class extends Log> logImpl) {
if (logImpl != null) {
this.logImpl = logImpl;
LogFactory.useCustomLogging(this.logImpl);
}
}
public Class extends VFS> getVfsImpl() {
return this.vfsImpl;
}
public void setVfsImpl(Class extends VFS> vfsImpl) {
if (vfsImpl != null) {
this.vfsImpl = vfsImpl;
VFS.addImplClass(this.vfsImpl);
}
}
public boolean isCallSettersOnNulls() {
return callSettersOnNulls;
}
public void setCallSettersOnNulls(boolean callSettersOnNulls) {
this.callSettersOnNulls = callSettersOnNulls;
}
public boolean isUseActualParamName() {
return useActualParamName;
}
public void setUseActualParamName(boolean useActualParamName) {
this.useActualParamName = useActualParamName;
}
public boolean isReturnInstanceForEmptyRow() {
return returnInstanceForEmptyRow;
}
public void setReturnInstanceForEmptyRow(boolean returnEmptyInstance) {
this.returnInstanceForEmptyRow = returnEmptyInstance;
}
public String getDatabaseId() {
return databaseId;
}
public void setDatabaseId(String databaseId) {
this.databaseId = databaseId;
}
public Class> getConfigurationFactory() {
return configurationFactory;
}
public void setConfigurationFactory(Class> configurationFactory) {
this.configurationFactory = configurationFactory;
}
public boolean isSafeResultHandlerEnabled() {
return safeResultHandlerEnabled;
}
public void setSafeResultHandlerEnabled(boolean safeResultHandlerEnabled) {
this.safeResultHandlerEnabled = safeResultHandlerEnabled;
}
public boolean isSafeRowBoundsEnabled() {
return safeRowBoundsEnabled;
}
public void setSafeRowBoundsEnabled(boolean safeRowBoundsEnabled) {
this.safeRowBoundsEnabled = safeRowBoundsEnabled;
}
public boolean isMapUnderscoreToCamelCase() {
return mapUnderscoreToCamelCase;
}
public void setMapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
}
public void addLoadedResource(String resource) {
loadedResources.add(resource);
}
public boolean isResourceLoaded(String resource) {
return loadedResources.contains(resource);
}
public Environment getEnvironment() {
return environment;
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
public AutoMappingBehavior getAutoMappingBehavior() {
return autoMappingBehavior;
}
public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
this.autoMappingBehavior = autoMappingBehavior;
}
/**
* @since 3.4.0
*/
public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() {
return autoMappingUnknownColumnBehavior;
}
/**
* @since 3.4.0
*/
public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) {
this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior;
}
public boolean isLazyLoadingEnabled() {
return lazyLoadingEnabled;
}
public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
this.lazyLoadingEnabled = lazyLoadingEnabled;
}
public ProxyFactory getProxyFactory() {
return proxyFactory;
}
public void setProxyFactory(ProxyFactory proxyFactory) {
if (proxyFactory == null) {
proxyFactory = new JavassistProxyFactory();
}
this.proxyFactory = proxyFactory;
}
public boolean isAggressiveLazyLoading() {
return aggressiveLazyLoading;
}
public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) {
this.aggressiveLazyLoading = aggressiveLazyLoading;
}
public boolean isMultipleResultSetsEnabled() {
return multipleResultSetsEnabled;
}
public void setMultipleResultSetsEnabled(boolean multipleResultSetsEnabled) {
this.multipleResultSetsEnabled = multipleResultSetsEnabled;
}
public Set getLazyLoadTriggerMethods() {
return lazyLoadTriggerMethods;
}
public void setLazyLoadTriggerMethods(Set lazyLoadTriggerMethods) {
this.lazyLoadTriggerMethods = lazyLoadTriggerMethods;
}
public boolean isUseGeneratedKeys() {
return useGeneratedKeys;
}
public void setUseGeneratedKeys(boolean useGeneratedKeys) {
this.useGeneratedKeys = useGeneratedKeys;
}
public ExecutorType getDefaultExecutorType() {
return defaultExecutorType;
}
public void setDefaultExecutorType(ExecutorType defaultExecutorType) {
this.defaultExecutorType = defaultExecutorType;
}
public boolean isCacheEnabled() {
return cacheEnabled;
}
public void setCacheEnabled(boolean cacheEnabled) {
this.cacheEnabled = cacheEnabled;
}
public Integer getDefaultStatementTimeout() {
return defaultStatementTimeout;
}
public void setDefaultStatementTimeout(Integer defaultStatementTimeout) {
this.defaultStatementTimeout = defaultStatementTimeout;
}
/**
* @since 3.3.0
*/
public Integer getDefaultFetchSize() {
return defaultFetchSize;
}
/**
* @since 3.3.0
*/
public void setDefaultFetchSize(Integer defaultFetchSize) {
this.defaultFetchSize = defaultFetchSize;
}
public boolean isUseColumnLabel() {
return useColumnLabel;
}
public void setUseColumnLabel(boolean useColumnLabel) {
this.useColumnLabel = useColumnLabel;
}
public LocalCacheScope getLocalCacheScope() {
return localCacheScope;
}
public void setLocalCacheScope(LocalCacheScope localCacheScope) {
this.localCacheScope = localCacheScope;
}
public JdbcType getJdbcTypeForNull() {
return jdbcTypeForNull;
}
public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) {
this.jdbcTypeForNull = jdbcTypeForNull;
}
public Properties getVariables() {
return variables;
}
public void setVariables(Properties variables) {
this.variables = variables;
}
public TypeHandlerRegistry getTypeHandlerRegistry() {
return typeHandlerRegistry;
}
public TypeAliasRegistry getTypeAliasRegistry() {
return typeAliasRegistry;
}
/**
* @since 3.2.2
*/
public MapperRegistry getMapperRegistry() {
return mapperRegistry;
}
public ReflectorFactory getReflectorFactory() {
return reflectorFactory;
}
public void setReflectorFactory(ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
}
public ObjectFactory getObjectFactory() {
return objectFactory;
}
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
public ObjectWrapperFactory getObjectWrapperFactory() {
return objectWrapperFactory;
}
public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) {
this.objectWrapperFactory = objectWrapperFactory;
}
public InterceptorChain getInterceptorChain() {
return interceptorChain;
}
/**
* @since 3.2.2
*/
public List getInterceptors() {
return interceptorChain.getInterceptors();
}
public LanguageDriverRegistry getLanguageRegistry() {
return languageRegistry;
}
public void setDefaultScriptingLanguage(Class> driver) {
if (driver == null) {
driver = XMLLanguageDriver.class;
}
getLanguageRegistry().setDefaultDriverClass(driver);
}
public LanguageDriver getDefaultScriptingLanguageInstance() {
return languageRegistry.getDefaultDriver();
}
/**
* @deprecated Use {@link #getDefaultScriptingLanguageInstance()}
*/
@Deprecated
public LanguageDriver getDefaultScriptingLanuageInstance() {
return getDefaultScriptingLanguageInstance();
}
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
public Executor newExecutor(Transaction transaction) {
return newExecutor(transaction, defaultExecutorType);
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
public void addKeyGenerator(String id, KeyGenerator keyGenerator) {
keyGenerators.put(id, keyGenerator);
}
public Collection getKeyGeneratorNames() {
return keyGenerators.keySet();
}
public Collection getKeyGenerators() {
return keyGenerators.values();
}
public KeyGenerator getKeyGenerator(String id) {
return keyGenerators.get(id);
}
public boolean hasKeyGenerator(String id) {
return keyGenerators.containsKey(id);
}
public void addCache(Cache cache) {
caches.put(cache.getId(), cache);
}
public Collection getCacheNames() {
return caches.keySet();
}
public Collection getCaches() {
return caches.values();
}
public Cache getCache(String id) {
return caches.get(id);
}
public boolean hasCache(String id) {
return caches.containsKey(id);
}
public void addResultMap(ResultMap rm) {
resultMaps.put(rm.getId(), rm);
checkLocallyForDiscriminatedNestedResultMaps(rm);
checkGloballyForDiscriminatedNestedResultMaps(rm);
}
public Collection getResultMapNames() {
return resultMaps.keySet();
}
public Collection getResultMaps() {
return resultMaps.values();
}
public ResultMap getResultMap(String id) {
return resultMaps.get(id);
}
public boolean hasResultMap(String id) {
return resultMaps.containsKey(id);
}
public void addParameterMap(ParameterMap pm) {
parameterMaps.put(pm.getId(), pm);
}
public Collection getParameterMapNames() {
return parameterMaps.keySet();
}
public Collection getParameterMaps() {
return parameterMaps.values();
}
public ParameterMap getParameterMap(String id) {
return parameterMaps.get(id);
}
public boolean hasParameterMap(String id) {
return parameterMaps.containsKey(id);
}
public void addMappedStatement(MappedStatement ms) {
mappedStatements.put(ms.getId(), ms);
}
public Collection getMappedStatementNames() {
buildAllStatements();
return mappedStatements.keySet();
}
public Collection getMappedStatements() {
buildAllStatements();
return mappedStatements.values();
}
public Collection getIncompleteStatements() {
return incompleteStatements;
}
public void addIncompleteStatement(XMLStatementBuilder incompleteStatement) {
incompleteStatements.add(incompleteStatement);
}
public Collection getIncompleteCacheRefs() {
return incompleteCacheRefs;
}
public void addIncompleteCacheRef(CacheRefResolver incompleteCacheRef) {
incompleteCacheRefs.add(incompleteCacheRef);
}
public Collection getIncompleteResultMaps() {
return incompleteResultMaps;
}
public void addIncompleteResultMap(ResultMapResolver resultMapResolver) {
incompleteResultMaps.add(resultMapResolver);
}
public void addIncompleteMethod(MethodResolver builder) {
incompleteMethods.add(builder);
}
public Collection getIncompleteMethods() {
return incompleteMethods;
}
public MappedStatement getMappedStatement(String id) {
return this.getMappedStatement(id, true);
}
public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
buildAllStatements();
}
return mappedStatements.get(id);
}
public Map getSqlFragments() {
return sqlFragments;
}
public void addInterceptor(Interceptor interceptor) {
interceptorChain.addInterceptor(interceptor);
}
public void addMappers(String packageName, Class> superType) {
mapperRegistry.addMappers(packageName, superType);
}
public void addMappers(String packageName) {
mapperRegistry.addMappers(packageName);
}
public void addMapper(Class type) {
mapperRegistry.addMapper(type);
}
public T getMapper(Class type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
public boolean hasMapper(Class> type) {
return mapperRegistry.hasMapper(type);
}
public boolean hasStatement(String statementName) {
return hasStatement(statementName, true);
}
public boolean hasStatement(String statementName, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
buildAllStatements();
}
return mappedStatements.containsKey(statementName);
}
public void addCacheRef(String namespace, String referencedNamespace) {
cacheRefMap.put(namespace, referencedNamespace);
}
/*
* Parses all the unprocessed statement nodes in the cache. It is recommended
* to call this method once all the mappers are added as it provides fail-fast
* statement validation.
*/
protected void buildAllStatements() {
if (!incompleteResultMaps.isEmpty()) {
synchronized (incompleteResultMaps) {
// This always throws a BuilderException.
incompleteResultMaps.iterator().next().resolve();
}
}
if (!incompleteCacheRefs.isEmpty()) {
synchronized (incompleteCacheRefs) {
// This always throws a BuilderException.
incompleteCacheRefs.iterator().next().resolveCacheRef();
}
}
if (!incompleteStatements.isEmpty()) {
synchronized (incompleteStatements) {
// This always throws a BuilderException.
incompleteStatements.iterator().next().parseStatementNode();
}
}
if (!incompleteMethods.isEmpty()) {
synchronized (incompleteMethods) {
// This always throws a BuilderException.
incompleteMethods.iterator().next().resolve();
}
}
}
/*
* Extracts namespace from fully qualified statement id.
*
* @param statementId
* @return namespace or null when id does not contain period.
*/
protected String extractNamespace(String statementId) {
int lastPeriod = statementId.lastIndexOf('.');
return lastPeriod > 0 ? statementId.substring(0, lastPeriod) : null;
}
// Slow but a one time cost. A better solution is welcome.
protected void checkGloballyForDiscriminatedNestedResultMaps(ResultMap rm) {
if (rm.hasNestedResultMaps()) {
for (Map.Entry entry : resultMaps.entrySet()) {
Object value = entry.getValue();
if (value instanceof ResultMap) {
ResultMap entryResultMap = (ResultMap) value;
if (!entryResultMap.hasNestedResultMaps() && entryResultMap.getDiscriminator() != null) {
Collection discriminatedResultMapNames = entryResultMap.getDiscriminator().getDiscriminatorMap().values();
if (discriminatedResultMapNames.contains(rm.getId())) {
entryResultMap.forceNestedResultMaps();
}
}
}
}
}
}
// Slow but a one time cost. A better solution is welcome.
protected void checkLocallyForDiscriminatedNestedResultMaps(ResultMap rm) {
if (!rm.hasNestedResultMaps() && rm.getDiscriminator() != null) {
for (Map.Entry entry : rm.getDiscriminator().getDiscriminatorMap().entrySet()) {
String discriminatedResultMapName = entry.getValue();
if (hasResultMap(discriminatedResultMapName)) {
ResultMap discriminatedResultMap = resultMaps.get(discriminatedResultMapName);
if (discriminatedResultMap.hasNestedResultMaps()) {
rm.forceNestedResultMaps();
break;
}
}
}
}
}
protected static class StrictMap<V> extends HashMap<String, V> {
private static final long serialVersionUID = -4950446264854982944L;
private final String name;
public StrictMap(String name, int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
this.name = name;
}
public StrictMap(String name, int initialCapacity) {
super(initialCapacity);
this.name = name;
}
public StrictMap(String name) {
super();
this.name = name;
}
public StrictMap(String name, Map m) {
super(m);
this.name = name;
}
@SuppressWarnings("unchecked")
public V put(String key, V value) {
if (containsKey(key)) {
throw new IllegalArgumentException(name + " already contains value for " + key);
}
if (key.contains(".")) {
final String shortKey = getShortName(key);
if (super.get(shortKey) == null) {
super.put(shortKey, value);
} else {
super.put(shortKey, (V) new Ambiguity(shortKey));
}
}
return super.put(key, value);
}
public V get(Object key) {
V value = super.get(key);
if (value == null) {
throw new IllegalArgumentException(name + " does not contain value for " + key);
}
if (value instanceof Ambiguity) {
throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
+ " (try using the full name including the namespace, or rename one of the entries)");
}
return value;
}
private String getShortName(String key) {
final String[] keyParts = key.split("\\.");
return keyParts[keyParts.length - 1];
}
protected static class Ambiguity {
final private String subject;
public Ambiguity(String subject) {
this.subject = subject;
}
public String getSubject() {
return subject;
}
}
}
}
intercept
package com.lf.plugin;
import com.lf.service.MypluginService;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.util.Properties;
/**
* Created by LF on 2017/6/11.
*/
@Intercepts({
//定义的方法签名
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = MypluginService.class, method = "test", args = {String.class})
})
public class MyBatisPlugin implements Interceptor {
@Override
//只有Intercepts在定义的方法才会被拦截
public Object intercept(Invocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
System.err.println("拦截的方法名是:" + name);
return invocation.proceed();
}
@Override
//生成一个代理对象
public Object plugin(Object target) {
System.err.println("代理的对象是:"+target);
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
Object name = properties.getProperty("name");//你好
System.err.println(name);
}
}
要拦截的接口
package com.lf.service;
/**
* Created by LF on 2017/6/11.
*/
public interface MypluginService {
String test(String string);
}
测试方法
package com.lf;
import com.lf.service.MypluginService;
import com.lf.service.impl.MypluginServiceImpl;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class App {
public static void main(String[] args) throws IOException {
String resouce = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resouce);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
MypluginService mypluginService = new MypluginServiceImpl();
SqlSession sqlSession = sqlSessionFactory.openSession();
Object o = sqlSessionFactory.getConfiguration().getInterceptorChain().pluginAll(mypluginService);
MypluginService mypluginService1 = (MypluginService) o;
((MypluginService) o).test("xxxxxxxx");
Object one = sqlSession.selectOne("com.lf.dao.BlogMapper.selectByPrimaryKey", "1");
System.err.println(one);
sqlSession.commit();
}
}