Mybatis源码学习二

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 }
 

猜你喜欢

转载自www.cnblogs.com/wk-missQ1/p/12635432.html