Mybatis执行一条查询语句的顺序代码:
1.入口就是配置类中的@MapperScan注解:
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring.annotation; 7 8 import java.lang.annotation.Annotation; 9 import java.lang.annotation.Documented; 10 import java.lang.annotation.ElementType; 11 import java.lang.annotation.Retention; 12 import java.lang.annotation.RetentionPolicy; 13 import java.lang.annotation.Target; 14 import org.mybatis.spring.mapper.MapperFactoryBean; 15 import org.springframework.beans.factory.support.BeanNameGenerator; 16 import org.springframework.context.annotation.Import; 17 18 @Retention(RetentionPolicy.RUNTIME) 19 @Target({ElementType.TYPE}) 20 @Documented 21 @Import({MapperScannerRegistrar.class}) 22 public @interface MapperScan { 23 String[] value() default {}; 24 25 String[] basePackages() default {}; 26 27 Class<?>[] basePackageClasses() default {}; 28 29 Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; 30 31 Class<? extends Annotation> annotationClass() default Annotation.class; 32 33 Class<?> markerInterface() default Class.class; 34 35 String sqlSessionTemplateRef() default ""; 36 37 String sqlSessionFactoryRef() default ""; 38 39 Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class; 40 }
2.进入@Import注解中的MapperScannerRegistrar类
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring.annotation; 7 8 import java.lang.annotation.Annotation; 9 import java.util.ArrayList; 10 import java.util.List; 11 import org.mybatis.spring.mapper.ClassPathMapperScanner; 12 import org.mybatis.spring.mapper.MapperFactoryBean; 13 import org.springframework.beans.BeanUtils; 14 import org.springframework.beans.factory.support.BeanDefinitionRegistry; 15 import org.springframework.beans.factory.support.BeanNameGenerator; 16 import org.springframework.context.ResourceLoaderAware; 17 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 18 import org.springframework.core.annotation.AnnotationAttributes; 19 import org.springframework.core.io.ResourceLoader; 20 import org.springframework.core.type.AnnotationMetadata; 21 import org.springframework.util.ClassUtils; 22 import org.springframework.util.StringUtils; 23 24 public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { 25 private ResourceLoader resourceLoader; 26 27 public MapperScannerRegistrar() { 28 } 29 30 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 31 AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); 32 ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); 33 if (this.resourceLoader != null) { 34 scanner.setResourceLoader(this.resourceLoader); 35 } 36 37 Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass"); 38 if (!Annotation.class.equals(annotationClass)) { 39 scanner.setAnnotationClass(annotationClass); 40 } 41 42 Class<?> markerInterface = annoAttrs.getClass("markerInterface"); 43 if (!Class.class.equals(markerInterface)) { 44 scanner.setMarkerInterface(markerInterface); 45 } 46 47 Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator"); 48 if (!BeanNameGenerator.class.equals(generatorClass)) { 49 scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass)); 50 } 51 52 Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); 53 if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { 54 scanner.setMapperFactoryBean((MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass)); 55 } 56 57 scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef")); 58 scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef")); 59 List<String> basePackages = new ArrayList(); 60 String[] var10 = annoAttrs.getStringArray("value"); 61 int var11 = var10.length; 62 63 int var12; 64 String pkg; 65 for(var12 = 0; var12 < var11; ++var12) { 66 pkg = var10[var12]; 67 if (StringUtils.hasText(pkg)) { 68 basePackages.add(pkg); 69 } 70 } 71 72 var10 = annoAttrs.getStringArray("basePackages"); 73 var11 = var10.length; 74 75 for(var12 = 0; var12 < var11; ++var12) { 76 pkg = var10[var12]; 77 if (StringUtils.hasText(pkg)) { 78 basePackages.add(pkg); 79 } 80 } 81 82 Class[] var14 = annoAttrs.getClassArray("basePackageClasses"); 83 var11 = var14.length; 84 85 for(var12 = 0; var12 < var11; ++var12) { 86 Class<?> clazz = var14[var12]; 87 basePackages.add(ClassUtils.getPackageName(clazz)); 88 } 89 90 scanner.registerFilters(); 91 scanner.doScan(StringUtils.toStringArray(basePackages)); 92 } 93 94 public void setResourceLoader(ResourceLoader resourceLoader) { 95 this.resourceLoader = resourceLoader; 96 } 97 }
3.进入MapperFactoryBean类中的getObject()方法。
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring.mapper; 7 8 import org.apache.ibatis.executor.ErrorContext; 9 import org.apache.ibatis.session.Configuration; 10 import org.mybatis.spring.support.SqlSessionDaoSupport; 11 import org.springframework.beans.factory.FactoryBean; 12 import org.springframework.util.Assert; 13 14 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { 15 private Class<T> mapperInterface; 16 private boolean addToConfig = true; 17 18 public MapperFactoryBean() { 19 } 20 21 public MapperFactoryBean(Class<T> mapperInterface) { 22 this.mapperInterface = mapperInterface; 23 } 24 25 protected void checkDaoConfig() { 26 super.checkDaoConfig(); 27 Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required"); 28 Configuration configuration = this.getSqlSession().getConfiguration(); 29 if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { 30 try { 31 configuration.addMapper(this.mapperInterface); 32 } catch (Exception var6) { 33 this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6); 34 throw new IllegalArgumentException(var6); 35 } finally { 36 ErrorContext.instance().reset(); 37 } 38 } 39 40 } 41 42 public T getObject() throws Exception { 43 return this.getSqlSession().getMapper(this.mapperInterface); 44 } 45 46 public Class<T> getObjectType() { 47 return this.mapperInterface; 48 } 49 50 public boolean isSingleton() { 51 return true; 52 } 53 54 public void setMapperInterface(Class<T> mapperInterface) { 55 this.mapperInterface = mapperInterface; 56 } 57 58 public Class<T> getMapperInterface() { 59 return this.mapperInterface; 60 } 61 62 public void setAddToConfig(boolean addToConfig) { 63 this.addToConfig = addToConfig; 64 } 65 66 public boolean isAddToConfig() { 67 return this.addToConfig; 68 } 69 }
4.getObject()方法中的getMapper()接口方法的具体实现:
如果是Mybatis与Spring想结合的时候,调用的是在SqlSessionTemplate类中的,所以进入SqlSessionTemplate类中的getMapper(Class<T> type)方法。
如果是Mybatis自己运行的时候,调用的是DefaultSqlSessio类中的。
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring; 7 8 import java.lang.reflect.InvocationHandler; 9 import java.lang.reflect.Method; 10 import java.lang.reflect.Proxy; 11 import java.sql.Connection; 12 import java.util.List; 13 import java.util.Map; 14 import org.apache.ibatis.cursor.Cursor; 15 import org.apache.ibatis.exceptions.PersistenceException; 16 import org.apache.ibatis.executor.BatchResult; 17 import org.apache.ibatis.reflection.ExceptionUtil; 18 import org.apache.ibatis.session.Configuration; 19 import org.apache.ibatis.session.ExecutorType; 20 import org.apache.ibatis.session.ResultHandler; 21 import org.apache.ibatis.session.RowBounds; 22 import org.apache.ibatis.session.SqlSession; 23 import org.apache.ibatis.session.SqlSessionFactory; 24 import org.springframework.beans.factory.DisposableBean; 25 import org.springframework.dao.support.PersistenceExceptionTranslator; 26 import org.springframework.util.Assert; 27 28 public class SqlSessionTemplate implements SqlSession, DisposableBean { 29 private final SqlSessionFactory sqlSessionFactory; 30 private final ExecutorType executorType; 31 private final SqlSession sqlSessionProxy; 32 private final PersistenceExceptionTranslator exceptionTranslator; 33 34 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { 35 this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); 36 } 37 38 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) { 39 this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true)); 40 } 41 42 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { 43 Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); 44 Assert.notNull(executorType, "Property 'executorType' is required"); 45 this.sqlSessionFactory = sqlSessionFactory; 46 this.executorType = executorType; 47 this.exceptionTranslator = exceptionTranslator; 48 this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor()); 49 } 50 51 public SqlSessionFactory getSqlSessionFactory() { 52 return this.sqlSessionFactory; 53 } 54 55 public ExecutorType getExecutorType() { 56 return this.executorType; 57 } 58 59 public PersistenceExceptionTranslator getPersistenceExceptionTranslator() { 60 return this.exceptionTranslator; 61 } 62 63 public <T> T selectOne(String statement) { 64 return this.sqlSessionProxy.selectOne(statement); 65 } 66 67 public <T> T selectOne(String statement, Object parameter) { 68 return this.sqlSessionProxy.selectOne(statement, parameter); 69 } 70 71 public <K, V> Map<K, V> selectMap(String statement, String mapKey) { 72 return this.sqlSessionProxy.selectMap(statement, mapKey); 73 } 74 75 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) { 76 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey); 77 } 78 79 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) { 80 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds); 81 } 82 83 public <T> Cursor<T> selectCursor(String statement) { 84 return this.sqlSessionProxy.selectCursor(statement); 85 } 86 87 public <T> Cursor<T> selectCursor(String statement, Object parameter) { 88 return this.sqlSessionProxy.selectCursor(statement, parameter); 89 } 90 91 public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) { 92 return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds); 93 } 94 95 public <E> List<E> selectList(String statement) { 96 return this.sqlSessionProxy.selectList(statement); 97 } 98 99 public <E> List<E> selectList(String statement, Object parameter) { 100 return this.sqlSessionProxy.selectList(statement, parameter); 101 } 102 103 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { 104 return this.sqlSessionProxy.selectList(statement, parameter, rowBounds); 105 } 106 107 public void select(String statement, ResultHandler handler) { 108 this.sqlSessionProxy.select(statement, handler); 109 } 110 111 public void select(String statement, Object parameter, ResultHandler handler) { 112 this.sqlSessionProxy.select(statement, parameter, handler); 113 } 114 115 public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { 116 this.sqlSessionProxy.select(statement, parameter, rowBounds, handler); 117 } 118 119 public int insert(String statement) { 120 return this.sqlSessionProxy.insert(statement); 121 } 122 123 public int insert(String statement, Object parameter) { 124 return this.sqlSessionProxy.insert(statement, parameter); 125 } 126 127 public int update(String statement) { 128 return this.sqlSessionProxy.update(statement); 129 } 130 131 public int update(String statement, Object parameter) { 132 return this.sqlSessionProxy.update(statement, parameter); 133 } 134 135 public int delete(String statement) { 136 return this.sqlSessionProxy.delete(statement); 137 } 138 139 public int delete(String statement, Object parameter) { 140 return this.sqlSessionProxy.delete(statement, parameter); 141 } 142 143 public <T> T getMapper(Class<T> type) { 144 return this.getConfiguration().getMapper(type, this); 145 } 146 147 public void commit() { 148 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession"); 149 } 150 151 public void commit(boolean force) { 152 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession"); 153 } 154 155 public void rollback() { 156 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession"); 157 } 158 159 public void rollback(boolean force) { 160 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession"); 161 } 162 163 public void close() { 164 throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession"); 165 } 166 167 public void clearCache() { 168 this.sqlSessionProxy.clearCache(); 169 } 170 171 public Configuration getConfiguration() { 172 return this.sqlSessionFactory.getConfiguration(); 173 } 174 175 public Connection getConnection() { 176 return this.sqlSessionProxy.getConnection(); 177 } 178 179 public List<BatchResult> flushStatements() { 180 return this.sqlSessionProxy.flushStatements(); 181 } 182 183 public void destroy() throws Exception { 184 } 185 186 private class SqlSessionInterceptor implements InvocationHandler { 187 private SqlSessionInterceptor() { 188 } 189 190 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 191 SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); 192 193 Object unwrapped; 194 try { 195 Object result = method.invoke(sqlSession, args); 196 if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { 197 sqlSession.commit(true); 198 } 199 200 unwrapped = result; 201 } catch (Throwable var11) { 202 unwrapped = ExceptionUtil.unwrapThrowable(var11); 203 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { 204 SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); 205 sqlSession = null; 206 Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped); 207 if (translated != null) { 208 unwrapped = translated; 209 } 210 } 211 212 throw (Throwable)unwrapped; 213 } finally { 214 if (sqlSession != null) { 215 SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); 216 } 217 218 } 219 220 return unwrapped; 221 } 222 } 223 }
5.进入getMapper()方法的实现类MapperRegistry类中。
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.apache.ibatis.binding; 7 8 import java.util.Collection; 9 import java.util.Collections; 10 import java.util.HashMap; 11 import java.util.Iterator; 12 import java.util.Map; 13 import java.util.Set; 14 import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder; 15 import org.apache.ibatis.io.ResolverUtil; 16 import org.apache.ibatis.io.ResolverUtil.IsA; 17 import org.apache.ibatis.session.Configuration; 18 import org.apache.ibatis.session.SqlSession; 19 20 public class MapperRegistry { 21 private final Configuration config; 22 private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap(); 23 24 public MapperRegistry(Configuration config) { 25 this.config = config; 26 } 27 28 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { 29 MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); 30 if (mapperProxyFactory == null) { 31 throw new BindingException("Type " + type + " is not known to the MapperRegistry."); 32 } else { 33 try { 34 return mapperProxyFactory.newInstance(sqlSession); 35 } catch (Exception var5) { 36 throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); 37 } 38 } 39 } 40 41 public <T> boolean hasMapper(Class<T> type) { 42 return this.knownMappers.containsKey(type); 43 } 44 45 public <T> void addMapper(Class<T> type) { 46 if (type.isInterface()) { 47 if (this.hasMapper(type)) { 48 throw new BindingException("Type " + type + " is already known to the MapperRegistry."); 49 } 50 51 boolean loadCompleted = false; 52 53 try { 54 this.knownMappers.put(type, new MapperProxyFactory(type)); 55 MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type); 56 parser.parse(); 57 loadCompleted = true; 58 } finally { 59 if (!loadCompleted) { 60 this.knownMappers.remove(type); 61 } 62 63 } 64 } 65 66 } 67 68 public Collection<Class<?>> getMappers() { 69 return Collections.unmodifiableCollection(this.knownMappers.keySet()); 70 } 71 72 public void addMappers(String packageName, Class<?> superType) { 73 ResolverUtil<Class<?>> resolverUtil = new ResolverUtil(); 74 resolverUtil.find(new IsA(superType), packageName); 75 Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses(); 76 Iterator var5 = mapperSet.iterator(); 77 78 while(var5.hasNext()) { 79 Class<?> mapperClass = (Class)var5.next(); 80 this.addMapper(mapperClass); 81 } 82 83 } 84 85 public void addMappers(String packageName) { 86 this.addMappers(packageName, Object.class); 87 } 88 }
6.查看方法得知这个方法主要处理的是一个Mapper的代理工厂,进入MapperProxyFactory。
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.apache.ibatis.binding; 7 8 import java.lang.reflect.Method; 9 import java.lang.reflect.Proxy; 10 import java.util.Map; 11 import java.util.concurrent.ConcurrentHashMap; 12 import org.apache.ibatis.session.SqlSession; 13 14 public class MapperProxyFactory<T> { 15 private final Class<T> mapperInterface; 16 private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap(); 17 18 public MapperProxyFactory(Class<T> mapperInterface) { 19 this.mapperInterface = mapperInterface; 20 } 21 22 public Class<T> getMapperInterface() { 23 return this.mapperInterface; 24 } 25 26 public Map<Method, MapperMethod> getMethodCache() { 27 return this.methodCache; 28 } 29 30 protected T newInstance(MapperProxy<T> mapperProxy) { 31 return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); 32 } 33 34 public T newInstance(SqlSession sqlSession) { 35 MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); 36 return this.newInstance(mapperProxy); 37 } 38 }
6.代理工厂MapperProxyFactory中产生的是MapperProxy类:
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.apache.ibatis.binding; 7 8 import java.io.Serializable; 9 import java.lang.invoke.MethodHandles; 10 import java.lang.invoke.MethodType; 11 import java.lang.invoke.MethodHandles.Lookup; 12 import java.lang.reflect.Constructor; 13 import java.lang.reflect.InvocationHandler; 14 import java.lang.reflect.Method; 15 import java.util.Map; 16 import org.apache.ibatis.reflection.ExceptionUtil; 17 import org.apache.ibatis.session.SqlSession; 18 19 public class MapperProxy<T> implements InvocationHandler, Serializable { 20 private static final long serialVersionUID = -6424540398559729838L; 21 private static final int ALLOWED_MODES = 15; 22 private static final Constructor<Lookup> lookupConstructor; 23 private static final Method privateLookupInMethod; 24 private final SqlSession sqlSession; 25 private final Class<T> mapperInterface; 26 private final Map<Method, MapperMethod> methodCache; 27 28 public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { 29 this.sqlSession = sqlSession; 30 this.mapperInterface = mapperInterface; 31 this.methodCache = methodCache; 32 } 33 34 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 35 try { 36 if (Object.class.equals(method.getDeclaringClass())) { 37 return method.invoke(this, args); 38 } 39 40 if (method.isDefault()) { 41 if (privateLookupInMethod == null) { 42 return this.invokeDefaultMethodJava8(proxy, method, args); 43 } 44 45 return this.invokeDefaultMethodJava9(proxy, method, args); 46 } 47 } catch (Throwable var5) { 48 throw ExceptionUtil.unwrapThrowable(var5); 49 } 50 51 MapperMethod mapperMethod = this.cachedMapperMethod(method); 52 return mapperMethod.execute(this.sqlSession, args); 53 } 54 55 private MapperMethod cachedMapperMethod(Method method) { 56 return (MapperMethod)this.methodCache.computeIfAbsent(method, (k) -> { 57 return new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration()); 58 }); 59 } 60 61 private Object invokeDefaultMethodJava9(Object proxy, Method method, Object[] args) throws Throwable { 62 Class<?> declaringClass = method.getDeclaringClass(); 63 return ((Lookup)privateLookupInMethod.invoke((Object)null, declaringClass, MethodHandles.lookup())).findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass).bindTo(proxy).invokeWithArguments(args); 64 } 65 66 private Object invokeDefaultMethodJava8(Object proxy, Method method, Object[] args) throws Throwable { 67 Class<?> declaringClass = method.getDeclaringClass(); 68 return ((Lookup)lookupConstructor.newInstance(declaringClass, 15)).unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args); 69 } 70 71 static { 72 Method privateLookupIn; 73 try { 74 privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, Lookup.class); 75 } catch (NoSuchMethodException var5) { 76 privateLookupIn = null; 77 } 78 79 privateLookupInMethod = privateLookupIn; 80 Constructor<Lookup> lookup = null; 81 if (privateLookupInMethod == null) { 82 try { 83 lookup = Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE); 84 lookup.setAccessible(true); 85 } catch (NoSuchMethodException var3) { 86 throw new IllegalStateException("There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.", var3); 87 } catch (Throwable var4) { 88 lookup = null; 89 } 90 } 91 92 lookupConstructor = lookup; 93 } 94 }
7.由于是代理方法,所以实现逻辑的部分是在这个invoke()方法中:
1 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 2 try { 3 if (Object.class.equals(method.getDeclaringClass())) { 4 return method.invoke(this, args); 5 } 6 7 if (method.isDefault()) { 8 if (privateLookupInMethod == null) { 9 return this.invokeDefaultMethodJava8(proxy, method, args); 10 } 11 12 return this.invokeDefaultMethodJava9(proxy, method, args); 13 } 14 } catch (Throwable var5) { 15 throw ExceptionUtil.unwrapThrowable(var5); 16 } 17 18 MapperMethod mapperMethod = this.cachedMapperMethod(method); 19 return mapperMethod.execute(this.sqlSession, args); 20 }
Mybatis与Spring结合的时候是怎么进行初始化的?
实现spring提供的一个InitializingBean接口,这个接口中的afterPropertiesSet()方法进行初始化。
在Mybatis中的MapperFactoryBean继承了SqlSessionDaoSupport,而SqlSessionDaoSupport继承自DaoSupport,DaoSupport实现了InitializingBean接口。
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring.mapper; 7 8 import org.apache.ibatis.executor.ErrorContext; 9 import org.apache.ibatis.session.Configuration; 10 import org.mybatis.spring.support.SqlSessionDaoSupport; 11 import org.springframework.beans.factory.FactoryBean; 12 import org.springframework.util.Assert; 13 14 public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { 15 private Class<T> mapperInterface; 16 private boolean addToConfig = true; 17 18 public MapperFactoryBean() { 19 } 20 21 public MapperFactoryBean(Class<T> mapperInterface) { 22 this.mapperInterface = mapperInterface; 23 } 24 25 protected void checkDaoConfig() { 26 super.checkDaoConfig(); 27 Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required"); 28 Configuration configuration = this.getSqlSession().getConfiguration(); 29 if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) { 30 try { 31 configuration.addMapper(this.mapperInterface); 32 } catch (Exception var6) { 33 this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6); 34 throw new IllegalArgumentException(var6); 35 } finally { 36 ErrorContext.instance().reset(); 37 } 38 } 39 40 } 41 42 public T getObject() throws Exception { 43 return this.getSqlSession().getMapper(this.mapperInterface); 44 } 45 46 public Class<T> getObjectType() { 47 return this.mapperInterface; 48 } 49 50 public boolean isSingleton() { 51 return true; 52 } 53 54 public void setMapperInterface(Class<T> mapperInterface) { 55 this.mapperInterface = mapperInterface; 56 } 57 58 public Class<T> getMapperInterface() { 59 return this.mapperInterface; 60 } 61 62 public void setAddToConfig(boolean addToConfig) { 63 this.addToConfig = addToConfig; 64 } 65 66 public boolean isAddToConfig() { 67 return this.addToConfig; 68 } 69 }
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.mybatis.spring.support; 7 8 import org.apache.ibatis.session.SqlSession; 9 import org.apache.ibatis.session.SqlSessionFactory; 10 import org.mybatis.spring.SqlSessionTemplate; 11 import org.springframework.dao.support.DaoSupport; 12 import org.springframework.util.Assert; 13 14 public abstract class SqlSessionDaoSupport extends DaoSupport { 15 private SqlSession sqlSession; 16 private boolean externalSqlSession; 17 18 public SqlSessionDaoSupport() { 19 } 20 21 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 22 if (!this.externalSqlSession) { 23 this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); 24 } 25 26 } 27 28 public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { 29 this.sqlSession = sqlSessionTemplate; 30 this.externalSqlSession = true; 31 } 32 33 public SqlSession getSqlSession() { 34 return this.sqlSession; 35 } 36 37 protected void checkDaoConfig() { 38 Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required"); 39 } 40 }
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.springframework.dao.support; 7 8 import org.apache.commons.logging.Log; 9 import org.apache.commons.logging.LogFactory; 10 import org.springframework.beans.factory.BeanInitializationException; 11 import org.springframework.beans.factory.InitializingBean; 12 13 public abstract class DaoSupport implements InitializingBean { 14 protected final Log logger = LogFactory.getLog(this.getClass()); 15 16 public DaoSupport() { 17 } 18 19 public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException { 20 this.checkDaoConfig(); 21 22 try { 23 this.initDao(); 24 } catch (Exception var2) { 25 throw new BeanInitializationException("Initialization of DAO failed", var2); 26 } 27 } 28 29 protected abstract void checkDaoConfig() throws IllegalArgumentException; 30 31 protected void initDao() throws Exception { 32 } 33 }
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.springframework.beans.factory; 7 8 public interface InitializingBean { 9 void afterPropertiesSet() throws Exception; 10 }