类加载器

Java自带有三个类加载器

image-20230615164339790

版本号

xml
1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
xml
1

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) {
//classpath下的
System.out.println(BindingException.class.getClassLoader());
// rt.jar包中的
System.out.println(String.class.getClassLoader());
}

sun.misc.Launcher$AppClassLoader@18b4aac2 // App ClassLoader
null // BootStrap ClassLoade 因为c写的所以打不出来

public static void main(String[] args) {
//classpath下的
System.out.println(BindingException.class.getClassLoader());
//BindingException.class.getClassLoader() 父加载器
System.out.println(BindingException.class.getClassLoader().getParent());
// rt.jar包中的
System.out.println(String.class.getClassLoader());
}

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@511d50c0
null

第一步:读取配置文件

java
1
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");

第二步:构建 SqlSessionFactory

java
1
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

第三步:打开 SqlSession

java
1
SqlSession sqlSession = sqlSessionFactory.openSession();

第四步:获取Mapper接口对象

java
1
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

第五步:调用Mapper接口对象方法操作数据库

java
1
2
3
4
User user = mapper.findOne();
// 显示查询结果
log.info("查询结果: " + user.getName() + "--" + user.getAge() + "--" + user.getId());
sqlSession.close();

————–

读取配置文件

第二步中,需要一个InputStream流,这里可以用mybatis提供的获取文件的,也可以自己去读取获得。

java
1
2
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-- 1
// 进入 getResourceAsStream
public static InputStream getResourceAsStream(String resource) throws IOException {
return getResourceAsStream(null, resource);
}

-- 2
// 此时传入进来的 ClassLoader 是等于 null 的, resource 是文件的名称
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if (in == null) { // 没读取到,直接抛异常
throw new IOException("Could not find resource " + resource);
}
return in;
}

-- 3
// 进入到ClassLoaderWrapper 的 getResourceAsStream 中发现需要获取 ClassLoader, 此时的 resource 是文件的名称, classLoader 为 null
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
return getResourceAsStream(resource, getClassLoaders(classLoader));
}

-- 3.1
// 发现 getClassLoaders 方法会返回五个 ClassLoader, 其中第一个为 null, 3、4、5都是AppclassLoader,多个类加载器主要是用于环境的适配,不同环境可能需要不同的方式来获取类加载器。
// 运行完后,返回到 -- 3
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
classLoader, // null
defaultClassLoader, // null
Thread.currentThread().getContextClassLoader(), // AppclassLoader
getClass().getClassLoader(), // AppclassLoader
systemClassLoader}; // AppclassLoader
}

-- 3.2
// 进入到 ClassLoaderWrapper 的 getResourceAsStream 中, 发现只是对上面传入的类加载器数组进行遍历,然后看哪一个加载器能够读到mybatis的配置文件,其中如果第一次读取读不到会在文件名字前面加 /(斜线),如果还读不到那就换下一个类加载器。直到最后返回这个 InputStream
// 最后一直返回到 -- 1
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
for (ClassLoader cl : classLoader) { // 遍历类加载器数组对象
if (null != cl) {

// try to find the resource as passed
InputStream returnValue = cl.getResourceAsStream(resource);

// now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
if (null == returnValue) {
returnValue = cl.getResourceAsStream("/" + resource); // 对文件名字加 /
}

if (null != returnValue) {
return returnValue;
}
}
}
return null;
}
– 3.1中所有的类加载器

image-20230810010317865

构建 SqlSessionFactory

java
1
2
// 通过 new 一个 SqlSessionFactoryBuilder 然后再去buil(), 会返回一个带 Configuration 的DefaultSqlSessionFactory, 其中documentBuilder会将mybatis.xml这个配置文件流解析成一个Document对象, 然后通过 XMLConfigBuilder.parse解析document对象后将返回一个Configuration对象 ,最后将这个Configuration这个对象传入到DefaultSqlSessionFactory的构造器,并且实例化返回
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SqlSessionFactoryBuilder {

...

public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}


public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); // 1
// 2
return build(parser.parse()); // parse Configuration对象
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

public SqlSessionFactory build(Configuration config) {
// 3
return new DefaultSqlSessionFactory(config); // 最终返回一个 DefaultSqlSessionFactory 对象
}

}
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
// XMLMapperEntityResolver() 仅仅new了个对象
// new XPathParser 会去初始化一些属性,并且将mybatis配置文件的流读取解析成一个Document对象
// this 构造器将自己的一些属性初始化
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver); // 初始化属性
this.document = createDocument(new InputSource(inputStream)); // 将配置文件内容放到ducoment对象中
}

// 对一些属性初始化
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
this.validation = validation;
this.entityResolver = entityResolver; // DTD离线解析
this.variables = variables;
XPathFactory factory = XPathFactory.newInstance();
this.xpath = factory.newXPath();
}

private Document createDocument(InputSource inputSource) {
...
return builder.parse(inputSource); // DocumentBuilder解析mybatis配置文件构建Document对象返回
...
}

// this 构造器
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration()); // 初始化 configuration
ErrorContext.instance().resource("SQL Mapper Configuration"); // ErrorContext是个单例,上下文错误信息记录, 里面是一个ThreadLocal的ErrorContext,对于当前线程是单例的
this.configuration.setVariables(props);// null
this.parsed = false;
this.environment = environment;
this.parser = parser; // xml解析器
}
public BaseBuilder(Configuration configuration) {
this.configuration = configuration; // 将configuration 赋值给父类的成员变量
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
java
1
2
3
4
5
6
7
8
9
10
// 将要解析document对象内容,将 configuration 标签下的所有配置项存储到Configuration对象中
2
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
Configuration 类

这个类主要是对mybati配置文件的对应封装,将配置文件中的属性和值放在这个类中,并且初始化一些配置别名

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 一些别名注册
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);
.....

// 配信信息存储容器
protected Properties variables = new Properties();
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();

protected boolean lazyLoadingEnabled = false;
protected ProxyFactory proxyFactory = new JavassistProxyFactory();
....

image-20230815114755270

打开 SqlSession

java
1
2
// 通过configuration中的environment对象获取transitionFactory, 再通过transitionFactory对象创建transition对象,将transition和executorType作为参数利用configuration对象创建一个执行器,最终将executor、configuration、autocommit作为参数传的defaultSqlSession创建对象并返回
SqlSession sqlSession = sqlSessionFactory.openSession();
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

public enum ExecutorType {
// SIMPLE 每次创建新的执行器
// REUSE 可复用一个执行器
// BATCH 批处理执行器
SIMPLE, REUSE, BATCH
}


private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
// 配置文件中的数据源的 environment
final Environment environment = configuration.getEnvironment();
// 获取事务工厂
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 创建一个事务 参数:数据源、事务隔离界别、是否自动提交事务,当前返回的是一个JDBC类型的事务
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器,参数:事务、执行器类型
final Executor executor = configuration.newExecutor(tx, execType);
// 最终将 配置信息对象、执行器、提交传入返回一个 DefaultSqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
// 上下文错误信息重置
ErrorContext.instance().reset();
}
}

// 数据源环境对象
public final class Environment {
private final String id;
private final TransactionFactory transactionFactory;
private final DataSource dataSource;
...
}
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
// 未配置环境或者未配置事务工厂,返回一个 ManagedTransactionFactory
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory(); // 配置文件中的事务工厂
}


// 当前配置的是JDBC,所以用的JDBC事务工厂创建的事务对象
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds; // 数据源
level = desiredLevel; // 隔离界别
autoCommit = desiredAutoCommit; // 是否自动提交
}

// 获取执行器, 根据执行器类型
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
// 判定两次,防止 defaultExecutorType 也为 null
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);
}
// mybatis缓存是否开启,这里会再次封装一次执行器(装饰器模式)
// 对 simpleExecutor 装饰
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// 通过拦截器,可对执行器注册插件(责任链模式)
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
public Object pluginAll(Object target) {
// mybatis xml拦截器标签
// <plugins>
// <plugin interceptor=""></plugin>
// </plugins>
// 遍历拦截器, 分页插件原理
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
// mybatis 示例
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
// JDK动态代理
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}


// 最终返回 DefaultSqlSession对象
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}

获取Mapper接口对象

java
1
2
// 通过Configuration中的mapperRegistry对象通过JDK动态代理创建一个MapperProxy对象返回
UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 其中会将Mapper对象使用JDK动态代理
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// DefaultSqlSession 类
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}

// Configuration 配置类
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// interface mapper.UserMapper
// type 表示当前获取的mapper接口,sqlSessio是前面DefaultSqlSession
// mapperRegistry是在构建Configuration就构建好了
return mapperRegistry.getMapper(type, sqlSession);
}

// private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// mapper代理工厂
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
// 工厂不存在,抛出异常
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
// 通过JDK代理创建一个Mapper代理对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}

// 创建mapper代理对象
public T newInstance(SqlSession sqlSession) {
// 参数 defaultSqlSession, interface mapper.UserMapper, {}
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
// JDK动态代理
return newInstance(mapperProxy);
}

protected T newInstance(MapperProxy<T> mapperProxy) {
// 返回代理对象
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

调用Mapper接口对象方法操作数据库

java
1
2
// mapper 是JDK代理对象
User user = mapper.findOne();
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
// 上面的mapper是个代理对象,所以直接进invoke了
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 当前方法的类是否是Object, 可能会调用一些Object的方法,比如hashCode、toString...
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
// 后面invoke里执行的查询
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}

private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
try {
return methodCache.computeIfAbsent(method, m -> {
// m 是否是默认方法(mapper接口中default关键字定义的)
if (m.isDefault()) {
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else {
// MapperMethod中会处理并存储一些sql信息和接口方法的信息(例如:sql语句、sql的类型、接口方法返回值类型、参数类型等)
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
});
} catch (RuntimeException re) {
Throwable cause = re.getCause();
throw cause == null ? re : cause;
}
}

// new MapperMethod..
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
// 主要存储sql信息
this.command = new SqlCommand(config, mapperInterface, method);
// 存储接口方法信息
this.method = new MethodSignature(config, mapperInterface, method);
}
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
// 方法名
final String methodName = method.getName();
// 方法所属接口class对象
final Class<?> declaringClass = method.getDeclaringClass();
// 从Configuration中获取MappedStatement对象
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
configuration);
if (ms == null) {
if (method.getAnnotation(Flush.class) != null) {
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): "
+ mapperInterface.getName() + "." + methodName);
}
} else {
// 方法名(包名 + 接口名 + 方法名)
name = ms.getId();
// sql类型(SELECT DELETE...)
type = ms.getSqlCommandType();
// 未知sql类型
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
// 方法返回结果参数类型
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
// 是否属于Class
if (resolvedReturnType instanceof Class<?>) {
// 转型
this.returnType = (Class<?>) resolvedReturnType;
// 是否属于 ParameterizedType
} else if (resolvedReturnType instanceof ParameterizedType) {
// 转型
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
// 直接通过method获取返回值类型
this.returnType = method.getReturnType();
}
// 一些判定赋值...
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
// 方法参数名字,例如@Param("id"), 下面这个构造器中就会将此方法的参数注解获取到,然后遍历注解拿到参数名字,如果不添加参数名字,则是arg0,arg1...
// 存储结构是个TreeMap,key是0,1,2...,value是arg0,arg1...或者id,name(@Param注解)..
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
public ParamNameResolver(Configuration config, Method method) {
// 参数类型
final Class<?>[] paramTypes = method.getParameterTypes();
// 参数注解
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
// 存储参数名
final SortedMap<Integer, String> map = new TreeMap<>();
// 参数个数
int paramCount = paramAnnotations.length;
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
// 特殊参数跳过,其中判定是否是RowBounds,ResultHandler的子类
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
// 遍历参数注释, 如果是Param的子类则赋值给name
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
break;
}
}
// 非Param子类, arg0...
if (name == null) {
// @Param was not specified.
if (config.isUseActualParamName()) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
name = String.valueOf(map.size());
}
}
map.put(paramIndex, name);
}
// 只读map
names = Collections.unmodifiableSortedMap(map);
}
// 仅仅有个invoke方法,有个模板
interface MapperMethodInvoker {
Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable;
}
// new PlainMethodInvoker..
// PlainMethodInvoker 实现于 MapperMethodInvoker
// 仅仅实例化
public PlainMethodInvoker(MapperMethod mapperMethod) {
super();
this.mapperMethod = mapperMethod;
}


public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
return mapperMethod.execute(sqlSession, args);
}
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
// sql 类型判定
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
// 更新
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
// 删除
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
// 查询
case SELECT:
// Void返回值,是否持有ResultHandle
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
// 返回多个
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
// 返回Map
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
// 返回游标
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
// 参数
Object param = method.convertArgsToSqlCommandParam(args);
// 执行查询
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
// 批量操作,提交到数据库
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.selectList(statement, parameter);
// 正确结构个数
if (list.size() == 1) {
return list.get(0);
// 单查询,返回多个结构,抛出异常
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
// wrapCollection 包装parram,一般类型直接返回
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// sql和参数信息
BoundSql boundSql = ms.getBoundSql(parameterObject);
// 缓存key,用于缓存查询结果(一级缓存)
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
// 一级缓存中没有,则再执行查询
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);// 清空缓存,如果在mapper标签中设置了 flushCache
// 是否使用缓存(useCache)
if (ms.isUseCache() && resultHandler == null) {
// 存储过程处理
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
// 尝试从缓存中获取结果
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) { // 如果没有重新查询
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
// 错误记录
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 清除缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
// 尝试从缓存中拿结果
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
// 存储函数处理
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
// 数据库查数据
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 模板方法-> 模板方法模式,由BaseExecutor声明方法模板,此次是执行SimpleExecutor的doQuery
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
// 放入缓存
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
// 策略模式,里面根据类型来返回对应的handle
// 实例化 + 插件注册
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 初始化statment
stmt = prepareStatement(handler, ms.getStatementLog());
// 执行execute()
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}

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);
// 注册插件(前面openSession时CachingExecutor注册过一次[装饰了SimpleExecutor])
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 带statementLog的链接对象
Connection connection = getConnection(statementLog);
// 设置一些值
stmt = handler.prepare(connection, transaction.getTimeout());
// 对statment设置值,类似JDBC中对?插槽设置值
handler.parameterize(stmt);
return stmt;
}
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.query(statement, resultHandler);
}
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行
ps.execute();
// 将ps中查询出来的值导入到集合中
return resultSetHandler.handleResultSets(ps);
}