带你学习Mybatis之ResultSetHandler结果集处理

ResultSetHandler结果集处理

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

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语句查询数据库得到的结果集.

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);
// resultSetCount初始为0
    while(rsw != null && resultMapCount > resultSetCount) {
      // 取出ResultMap
        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的映射

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());
    }

}
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处理简单映射
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值定位到指定的记录行,使用的是逻辑分页,如果数据量太大会导致内存溢出,最好实现分页方法而不是使用mybatis的默认分页
    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处理嵌套映射
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中,如果一个对象的某个属性需要延迟加载,那么在影射该属性时,会将该属性创建相应的代理对象并返回;当真正要使用延迟加载的属性时,会通过代理对象执行数据库加载操作,得到真正的数据。

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

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

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

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

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

CGLIB

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

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就可以动态的修改类的结构,或是动态的生成类。

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);
    }
}
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负责保存一次延迟加载操作所需的全部信息

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
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
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");
            
        } 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 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
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");
            
        } 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 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);
            }
        }
    }
}

https://zhhll.icu/2020/框架/mybatis/组件分析/9.mybatis之ResultSetHandler结果集处理/

本文由mdnice多平台发布

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾光师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值