0%

mybatis之ResultSetHandler结果集处理

ResultSetHandler结果集处理

在StatementHandler接口在执行完指定的select语句之后,会将查询得到的结果集交给ResultSetHandler完成映射处理。ResultSetHandler除了负责映射select语句查询得到的结果集,还会处理存储过程执行后的输出参数。

1
2
3
4
5
6
7
8
9
10
11
12
public interface ResultSetHandler {

// 处理结果集,生成相应的结果对象集合
<E> List<E> handleResultSets(Statement stmt) throws SQLException;

// 处理结果集,返回相应的游标对象
<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

// 处理存储过程的输出参数
void handleOutputParameters(CallableStatement cs) throws SQLException;

}

DefaultResultSetHandler

DefaultResultSetHandler是mybatis提供的resultSetHandler接口的唯一实现.

handleResultSets方法

处理select语句查询数据库得到的结果集.

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
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId());
// 用于保存映射结果集得到的结果对象
List<Object> multipleResults = new ArrayList();
int resultSetCount = 0;
// 获取第一个ResultSet对象(可能存在多个ResultSet,只获取第一个)
ResultSetWrapper rsw = this.getFirstResultSet(stmt);
// 获取在配置文件中配置的resultMap
List<ResultMap> resultMaps = this.mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
this.validateResultMapsCount(rsw, resultMapCount);

while(rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount);
// 根据ResultMap中定义的映射规则对ResultSet进行映射,将映射的结果对象添加到multipleResults中
this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null);
// 获取下一个结果集
rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
// 获取MappedStatement.resultSets属性,该属性仅对于多结果集的情况适用,该属性将列出语句执行后返回的结果集,并给每个结果集一个名称,名称使用逗号分隔
String[] resultSets = this.mappedStatement.getResultSets();
if (resultSets != null) {
while(rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId);
this.handleResultSet(rsw, resultMap, (List)null, parentMapping);
}

rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
}

return this.collapseSingleResultList(multipleResults);
}

handleResultSet方法

handleResultSet该方法用来完成单个ResultSet的映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
try {
if (parentMapping != null) {
// 处理多结果集中的嵌套映射
this.handleRowValues(rsw, resultMap, (ResultHandler)null, RowBounds.DEFAULT, parentMapping);
} else if (this.resultHandler == null) { // 没有指定ResultHandler,适用默认的
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(this.objectFactory);
// 对ResultSet进行映射,将结果对象放到defaultResultHandler中暂存
this.handleRowValues(rsw, resultMap, defaultResultHandler, this.rowBounds, (ResultMapping)null);
multipleResults.add(defaultResultHandler.getResultList());
} else {
// 适用用户指定的resultHandler
this.handleRowValues(rsw, resultMap, this.resultHandler, this.rowBounds, (ResultMapping)null);
}
} finally {
this.closeResultSet(rsw.getResultSet());
}

}
1
2
3
4
5
6
7
8
9
10
11
12
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
// 存在嵌套结果集的情况
if (resultMap.hasNestedResultMaps()) {
this.ensureNoRowBounds();
this.checkResultHandler();
this.handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
//不存在嵌套结果集的情况
this.handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}

}
handleRowValuesForSimpleResultMap处理简单映射
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext();
ResultSet resultSet = rsw.getResultSet();
// 根据rowBounds中的offset值定位到指定的记录行
this.skipRows(resultSet, rowBounds);
// 检测是否还有需要映射的记录
while(this.shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) { // 确定映射使用的ResultMap对象
ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(resultSet, resultMap, (String)null);
// 对ResultSet中的一行记录进行映射
Object rowValue = this.getRowValue(rsw, discriminatedResultMap, (String)null);
this.storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}

}
handleRowValuesForNestedResultMap处理嵌套映射
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
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext();
ResultSet resultSet = rsw.getResultSet();
// 根据offset定位指定的记录行
this.skipRows(resultSet, rowBounds);
Object rowValue = this.previousRowValue;
// 检测是否能继续映射结果集中剩余的记录行
while(this.shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(resultSet, resultMap, (String)null);
CacheKey rowKey = this.createRowKey(discriminatedResultMap, rsw, (String)null);
Object partialObject = this.nestedResultObjects.get(rowKey);
if (this.mappedStatement.isResultOrdered()) {
if (partialObject == null && rowValue != null) {
this.nestedResultObjects.clear();
this.storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}

rowValue = this.getRowValue(rsw, discriminatedResultMap, rowKey, (String)null, partialObject);
} else {
rowValue = this.getRowValue(rsw, discriminatedResultMap, rowKey, (String)null, partialObject);
if (partialObject == null) {
this.storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}
}

if (rowValue != null && this.mappedStatement.isResultOrdered() && this.shouldProcessMoreRows(resultContext, rowBounds)) {
this.storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
this.previousRowValue = null;
} else if (rowValue != null) {
this.previousRowValue = rowValue;
}

}

延迟加载

延迟加载表示:暂时不用的对象不会真正载入到内存中,知道真正需要使用该对象时,才会去执行数据库查询操作,将该对象加载到内存中。在Mybatis中,如果一个对象的某个属性需要延迟加载,那么在影射该属性时,会将该属性创建相应的代理对象并返回;当真正要使用延迟加载的属性时,会通过代理对象执行数据库加载操作,得到真正的数据。

延迟加载配置
  • 属性在中的相应节点配置了fetchType属性,则按照fetchType属性决定是否延迟加载

  • 未配置fetchType属性,则需要根据mybatis-config.xml配置文件中的lazyLoadingEnabled配置是否延时加载

    1
    2
    3
    4
    <!-- 打开延时操作的开关 -->
    <settings name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为按需加载 false为按需加载-->
    <settings name="aggressiveLazyLoading" value="false"/>
延迟加载原理

延迟加载使用动态代理实现的,由于映射的结果对象都为普通的类,没有使用接口,所以无法使用JDK代理

mybatis提供了两种为普通类动态生成代理对象的方式,为CGLIB方式和JAVASSIST方式

CGLIB

CGLIB采用字节码技术实现动态代理功能,原理是通过字节码技术为目标类生成子类,并在子类中采用方法拦截的方式拦截所有父类方法的调用,从而实现代理的功能。

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
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();

public Object getProxy(Class clazz){
// 指定代理类的父类
enhancer.setSuperclass(clazz);
// 设置Callback对象
enhancer.setCallback(this);
// 通过字节码技术动态创建子类实例
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置处理");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("后置处理");
return result;
}
}


public class Test {

public void print(){
System.out.println("方法执行");
}

public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
Test proxyImp = (Test) proxy.getProxy(Test.class);
proxyImp.print();

}
}
Javassist

Javassist是一个开源的生成java字节码的类库,其主要优点在于简单、快速,直接使用Javassist提供的API就可以动态的修改类的结构,或是动态的生成类。

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
public class Test {
public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
// 创建ClassPool
ClassPool classPool = ClassPool.getDefault();
// 生成类com.zhanghe.study.Gen
CtClass ctClass = classPool.makeClass("com.zhanghe.study.Gen");
StringBuffer body = null;
// 创建字段,指定字段类型、名称、所属类
CtField ctField = new CtField(classPool.get("java.lang.String"),"prop",ctClass);
// 设置为私有属性
ctField.setModifiers(Modifier.PRIVATE);
// 添加属性
ctClass.addField(ctField);
//getter/setter方法
ctClass.addMethod(CtNewMethod.getter("getProp",ctField));
ctClass.addMethod(CtNewMethod.setter("setProp",ctField));
// 创建execute方法 方法返回值、方法名称、方法入参。方法所属类
CtMethod ctMethod = new CtMethod(CtClass.voidType,"execute",new CtClass[]{},ctClass);
ctMethod.setModifiers(Modifier.PUBLIC);

body = new StringBuffer();
body.append("\n System.out.println(\"execute()方法执行\");");
body.append("\n");
// 设置方法体
ctMethod.setBody(body.toString());
ctClass.addMethod(ctMethod);
// 将类保存到文件中
ctClass.writeFile("./target/classes");

Class clazz = ctClass.toClass();
Object obj = clazz.newInstance();
Method method = obj.getClass().getMethod("setProp",String.class);
method.invoke(obj,"测试");

Method getMethod = obj.getClass().getMethod("getProp");
System.out.println(getMethod.invoke(obj));

Method exeMethod = obj.getClass().getMethod("execute");
exeMethod.invoke(obj);
}
}
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
public class JavassistMain {
public void test(){
System.out.println("执行");
}
}


public class JavassistTest {

public static ProxyFactory createProxy(){
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(JavassistMain.class);
// 设置拦截器
factory.setFilter(method -> {
if("test".equals(method.getName())){
return true;
}
return false;
});


return factory;
}

public static void main(String[] args) throws IllegalAccessException, InstantiationException {
ProxyFactory factory = createProxy();
Class clazz = factory.createClass();

Object obj = clazz.newInstance();
((ProxyObject)obj).setHandler(new MyMethodHandler());
((JavassistMain)obj).test();

}
}


public class MyMethodHandler implements MethodHandler {
@Override
/**
* self 生成的代理类
* method 原始的方法
* process 生成代理类的代理方法
* objects 方法入参
*/
public Object invoke(Object self, Method method, Method process, Object[] objects) throws Throwable {
System.out.println("前置处理");
Object obj = process.invoke(self,objects);
System.out.println("后置处理");
return obj;
}
}
ResultLoader

ResultLoader负责保存一次延迟加载操作所需的全部信息

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
public class ResultLoader {
protected final Configuration configuration;
protected final Executor executor;
protected final MappedStatement mappedStatement;
protected final Object parameterObject;
// 延迟加载得到的对象类型
protected final Class<?> targetType;
// 通过反射创建延迟加载对象
protected final ObjectFactory objectFactory;
protected final CacheKey cacheKey;
// 记录延迟执行的SQL语句以及相关配置信息
protected final BoundSql boundSql;
// 负责将延迟加载得到的结果对象转换为targetType类型的对象
protected final ResultExtractor resultExtractor;
protected final long creatorThreadId;
protected boolean loaded;
// 延迟加载得到的结果对象
protected Object resultObject;

public ResultLoader(Configuration config, Executor executor, MappedStatement mappedStatement, Object parameterObject, Class<?> targetType, CacheKey cacheKey, BoundSql boundSql) {
this.configuration = config;
this.executor = executor;
this.mappedStatement = mappedStatement;
this.parameterObject = parameterObject;
this.targetType = targetType;
this.objectFactory = this.configuration.getObjectFactory();
this.cacheKey = cacheKey;
this.boundSql = boundSql;
this.resultExtractor = new ResultExtractor(this.configuration, this.objectFactory);
this.creatorThreadId = Thread.currentThread().getId();
}

public Object loadResult() throws SQLException {
// 执行延迟加载,得到结果对象
List<Object> list = this.selectList();
// 将list集合转换为targetType指定类型的对象
this.resultObject = this.resultExtractor.extractObjectFromList(list, this.targetType);
return this.resultObject;
}

private <E> List<E> selectList() throws SQLException {
Executor localExecutor = this.executor;
// 检测调用该方法的线程是否为创建ResultLoader对象的线程、检测localExecutor是否关闭
if (Thread.currentThread().getId() != this.creatorThreadId || localExecutor.isClosed()) {
localExecutor = this.newExecutor();
}

List var2;
try {
// 执行查询操作,得到延迟加载的对象。
var2 = localExecutor.query(this.mappedStatement, this.parameterObject, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, this.cacheKey, this.boundSql);
} finally {
if (localExecutor != this.executor) {
localExecutor.close(false);
}

}

return var2;
}

private Executor newExecutor() {
Environment environment = this.configuration.getEnvironment();
if (environment == null) {
throw new ExecutorException("ResultLoader could not load lazily. Environment was not configured.");
} else {
DataSource ds = environment.getDataSource();
if (ds == null) {
throw new ExecutorException("ResultLoader could not load lazily. DataSource was not configured.");
} else {
TransactionFactory transactionFactory = environment.getTransactionFactory();
Transaction tx = transactionFactory.newTransaction(ds, (TransactionIsolationLevel)null, false);
return this.configuration.newExecutor(tx, ExecutorType.SIMPLE);
}
}
}

public boolean wasNull() {
return this.resultObject == null;
}
}
ProxyFactory
1
2
3
4
5
6
public interface ProxyFactory {
default void setProperties(Properties properties) {
}
// 创建代理对象
Object createProxy(Object var1, ResultLoaderMap var2, Configuration var3, ObjectFactory var4, List<Class<?>> var5, List<Object> var6);
}

有两个子类,CglibProxyFactory和JavassistProxyFactory

CglibProxyFactory
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
public class CglibProxyFactory implements ProxyFactory {
private static final String FINALIZE_METHOD = "finalize";
private static final String WRITE_REPLACE_METHOD = "writeReplace";

public CglibProxyFactory() {
try {
Resources.classForName("net.sf.cglib.proxy.Enhancer");
} catch (Throwable var2) {
throw new IllegalStateException("Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath.", var2);
}
}

public Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return CglibProxyFactory.EnhancedResultObjectProxyImpl.createProxy(target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}

public Object createDeserializationProxy(Object target, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return CglibProxyFactory.EnhancedDeserializationProxyImpl.createProxy(target, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}

static Object crateProxy(Class<?> type, Callback callback, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Enhancer enhancer = new Enhancer();
enhancer.setCallback(callback);
enhancer.setSuperclass(type);

try {
type.getDeclaredMethod("writeReplace");
if (CglibProxyFactory.LogHolder.log.isDebugEnabled()) {
CglibProxyFactory.LogHolder.log.debug("writeReplace method was found on bean " + type + ", make sure it returns this");
}
} catch (NoSuchMethodException var8) {
enhancer.setInterfaces(new Class[]{WriteReplaceInterface.class});
} catch (SecurityException var9) {
}

Object enhanced;
if (constructorArgTypes.isEmpty()) {
enhanced = enhancer.create();
} else {
Class<?>[] typesArray = (Class[])constructorArgTypes.toArray(new Class[constructorArgTypes.size()]);
Object[] valuesArray = constructorArgs.toArray(new Object[constructorArgs.size()]);
enhanced = enhancer.create(typesArray, valuesArray);
}

return enhanced;
}

private static class LogHolder {
private static final Log log = LogFactory.getLog(CglibProxyFactory.class);

private LogHolder() {
}
}

private static class EnhancedDeserializationProxyImpl extends AbstractEnhancedDeserializationProxy implements MethodInterceptor {
private EnhancedDeserializationProxyImpl(Class<?> type, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
super(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}

public static Object createProxy(Object target, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> type = target.getClass();
CglibProxyFactory.EnhancedDeserializationProxyImpl callback = new CglibProxyFactory.EnhancedDeserializationProxyImpl(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
Object enhanced = CglibProxyFactory.crateProxy(type, callback, constructorArgTypes, constructorArgs);
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}

public Object intercept(Object enhanced, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object o = super.invoke(enhanced, method, args);
return o instanceof AbstractSerialStateHolder ? o : methodProxy.invokeSuper(o, args);
}

protected AbstractSerialStateHolder newSerialStateHolder(Object userBean, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return new CglibSerialStateHolder(userBean, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}
}

private static class EnhancedResultObjectProxyImpl implements MethodInterceptor {
private final Class<?> type;
private final ResultLoaderMap lazyLoader;
private final boolean aggressive;
private final Set<String> lazyLoadTriggerMethods;
private final ObjectFactory objectFactory;
private final List<Class<?>> constructorArgTypes;
private final List<Object> constructorArgs;

private EnhancedResultObjectProxyImpl(Class<?> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
this.type = type;
this.lazyLoader = lazyLoader;
this.aggressive = configuration.isAggressiveLazyLoading();
this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods();
this.objectFactory = objectFactory;
this.constructorArgTypes = constructorArgTypes;
this.constructorArgs = constructorArgs;
}

public static Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> type = target.getClass();
CglibProxyFactory.EnhancedResultObjectProxyImpl callback = new CglibProxyFactory.EnhancedResultObjectProxyImpl(type, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
Object enhanced = CglibProxyFactory.crateProxy(type, callback, constructorArgTypes, constructorArgs);
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}

public Object intercept(Object enhanced, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
String methodName = method.getName();

try {
synchronized(this.lazyLoader) {
if ("writeReplace".equals(methodName)) {
Object original;
if (this.constructorArgTypes.isEmpty()) {
original = this.objectFactory.create(this.type);
} else {
original = this.objectFactory.create(this.type, this.constructorArgTypes, this.constructorArgs);
}

PropertyCopier.copyBeanProperties(this.type, enhanced, original);
if (this.lazyLoader.size() > 0) {
return new CglibSerialStateHolder(original, this.lazyLoader.getProperties(), this.objectFactory, this.constructorArgTypes, this.constructorArgs);
}

return original;
}
// 是否有延迟加载属性
if (this.lazyLoader.size() > 0 && !"finalize".equals(methodName)) {
// aggressiveLazyLoading配置为true,或者调用的方法在lazyLoadTriggerMethods中,将全部属性加载完
if (!this.aggressive && !this.lazyLoadTriggerMethods.contains(methodName)) {
String property;
if (PropertyNamer.isSetter(methodName)) {
property = PropertyNamer.methodToProperty(methodName);
this.lazyLoader.remove(property);
}
// 调用了某属性的getter方法,现获取该属性的名称
else if (PropertyNamer.isGetter(methodName)) {
property = PropertyNamer.methodToProperty(methodName);
// 该属性是否为延迟加载属性
if (this.lazyLoader.hasLoader(property)) {
// 触发该属性的延迟加载操作
this.lazyLoader.load(property);
}
}
} else {
this.lazyLoader.loadAll();
}
}
}

return methodProxy.invokeSuper(enhanced, args);
} catch (Throwable var10) {
throw ExceptionUtil.unwrapThrowable(var10);
}
}
}
}
JavassistProxyFactory
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
public class JavassistProxyFactory implements ProxyFactory {
private static final String FINALIZE_METHOD = "finalize";
private static final String WRITE_REPLACE_METHOD = "writeReplace";

public JavassistProxyFactory() {
try {
Resources.classForName("org.apache.ibatis.javassist.util.proxy.ProxyFactory");
} catch (Throwable var2) {
throw new IllegalStateException("Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.", var2);
}
}

public Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return JavassistProxyFactory.EnhancedResultObjectProxyImpl.createProxy(target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}

public Object createDeserializationProxy(Object target, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return JavassistProxyFactory.EnhancedDeserializationProxyImpl.createProxy(target, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}

static Object crateProxy(Class<?> type, MethodHandler callback, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
org.apache.ibatis.javassist.util.proxy.ProxyFactory enhancer = new org.apache.ibatis.javassist.util.proxy.ProxyFactory();
enhancer.setSuperclass(type);

try {
type.getDeclaredMethod("writeReplace");
if (JavassistProxyFactory.LogHolder.log.isDebugEnabled()) {
JavassistProxyFactory.LogHolder.log.debug("writeReplace method was found on bean " + type + ", make sure it returns this");
}
} catch (NoSuchMethodException var10) {
enhancer.setInterfaces(new Class[]{WriteReplaceInterface.class});
} catch (SecurityException var11) {
}

Class<?>[] typesArray = (Class[])constructorArgTypes.toArray(new Class[constructorArgTypes.size()]);
Object[] valuesArray = constructorArgs.toArray(new Object[constructorArgs.size()]);

Object enhanced;
try {
enhanced = enhancer.create(typesArray, valuesArray);
} catch (Exception var9) {
throw new ExecutorException("Error creating lazy proxy. Cause: " + var9, var9);
}

((Proxy)enhanced).setHandler(callback);
return enhanced;
}

private static class LogHolder {
private static final Log log = LogFactory.getLog(JavassistProxyFactory.class);

private LogHolder() {
}
}

private static class EnhancedDeserializationProxyImpl extends AbstractEnhancedDeserializationProxy implements MethodHandler {
private EnhancedDeserializationProxyImpl(Class<?> type, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
super(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}

public static Object createProxy(Object target, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> type = target.getClass();
JavassistProxyFactory.EnhancedDeserializationProxyImpl callback = new JavassistProxyFactory.EnhancedDeserializationProxyImpl(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
Object enhanced = JavassistProxyFactory.crateProxy(type, callback, constructorArgTypes, constructorArgs);
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}

public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
Object o = super.invoke(enhanced, method, args);
return o instanceof AbstractSerialStateHolder ? o : methodProxy.invoke(o, args);
}

protected AbstractSerialStateHolder newSerialStateHolder(Object userBean, Map<String, LoadPair> unloadedProperties, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return new JavassistSerialStateHolder(userBean, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}
}

private static class EnhancedResultObjectProxyImpl implements MethodHandler {
private final Class<?> type;
private final ResultLoaderMap lazyLoader;
private final boolean aggressive;
private final Set<String> lazyLoadTriggerMethods;
private final ObjectFactory objectFactory;
private final List<Class<?>> constructorArgTypes;
private final List<Object> constructorArgs;

private EnhancedResultObjectProxyImpl(Class<?> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
this.type = type;
this.lazyLoader = lazyLoader;
this.aggressive = configuration.isAggressiveLazyLoading();
this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods();
this.objectFactory = objectFactory;
this.constructorArgTypes = constructorArgTypes;
this.constructorArgs = constructorArgs;
}

public static Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> type = target.getClass();
JavassistProxyFactory.EnhancedResultObjectProxyImpl callback = new JavassistProxyFactory.EnhancedResultObjectProxyImpl(type, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
Object enhanced = JavassistProxyFactory.crateProxy(type, callback, constructorArgTypes, constructorArgs);
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}

public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
String methodName = method.getName();

try {
synchronized(this.lazyLoader) {
if ("writeReplace".equals(methodName)) {
Object original;
if (this.constructorArgTypes.isEmpty()) {
original = this.objectFactory.create(this.type);
} else {
original = this.objectFactory.create(this.type, this.constructorArgTypes, this.constructorArgs);
}

PropertyCopier.copyBeanProperties(this.type, enhanced, original);
if (this.lazyLoader.size() > 0) {
return new JavassistSerialStateHolder(original, this.lazyLoader.getProperties(), this.objectFactory, this.constructorArgTypes, this.constructorArgs);
}

return original;
}

if (this.lazyLoader.size() > 0 && !"finalize".equals(methodName)) {
if (!this.aggressive && !this.lazyLoadTriggerMethods.contains(methodName)) {
String property;
if (PropertyNamer.isSetter(methodName)) {
property = PropertyNamer.methodToProperty(methodName);
this.lazyLoader.remove(property);
} else if (PropertyNamer.isGetter(methodName)) {
property = PropertyNamer.methodToProperty(methodName);
if (this.lazyLoader.hasLoader(property)) {
this.lazyLoader.load(property);
}
}
} else {
this.lazyLoader.loadAll();
}
}
}

return methodProxy.invoke(enhanced, args);
} catch (Throwable var10) {
throw ExceptionUtil.unwrapThrowable(var10);
}
}
}
}