【深入理解Spring系列2】动态代理

Spring 动态代理

以mybatis-spring为例子讲下Spring的动态代理过程。
mybatis官网:https://mybatis.org/mybatis-3/zh

  • 动态代理的关键
  1. 新建

JDK的动态代理。

1
Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

mapperProxy实现了InvocationHanlder
mapperInterface是这个new出来的类接口。接口与实现是分开的。
mybatis的关键点:

1
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);

sqlSession在这里传入 MapperProxy
MapperProxy又调用MapperMethod
Mybatis Mapper具体的代理方法的实现在这里
MybatisMapperRegistry.addMapper(Class)

1
MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);

MybatisMapperAnnotationBuilder

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
@Override
@SuppressWarnings("unchecked")
public void parse() {
String resource = type.toString();
if (!configuration.isResourceLoaded(resource)) {
loadXmlResource();
configuration.addLoadedResource(resource);
assistant.setCurrentNamespace(type.getName());
parseCache();
parseCacheRef();
Method[] methods = type.getMethods();
// TODO 注入 CURD 动态 SQL (应该在注解之前注入)
if (GlobalConfigUtils.getSuperMapperClass(configuration).isAssignableFrom(type)) {
GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
}
for (Method method : methods) {
try {
// issue #237
if (!method.isBridge()) {
parseStatement(method);
}
} catch (IncompleteElementException e) {
/*
* 使用 MybatisMethodResolver 而不是 MethodResolver
*/
configuration.addIncompleteMethod(new MybatisMethodResolver(this, method));
}
}
}
parsePendingMethods();
}

mybatis两种:

  • 初始化

  • 执行过程