/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor.loader;
import java.util.List;
import java.util.Properties;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.session.Configuration;
/**
* 懒加载代理工厂
* @author Eduardo Macarron
*/
public interface ProxyFactory {
/**
* 用于配置属性,用于使用者自定义实现类的时候进行扩展
* @param properties 属性集
*/
void setProperties(Properties properties);
/**
* 创建代理对象
* @param target 结果对象
* @param lazyLoader 用来表示需要懒加载的属性集,本质是一个HashMap
* @param configuration Mybatis全局配置信息
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 代理对象
*/
Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List
CglibProxyFactory
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor.loader.cglib;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.ibatis.executor.loader.AbstractEnhancedDeserializationProxy;
import org.apache.ibatis.executor.loader.AbstractSerialStateHolder;
import org.apache.ibatis.executor.loader.ProxyFactory;
import org.apache.ibatis.executor.loader.ResultLoaderMap;
import org.apache.ibatis.executor.loader.WriteReplaceInterface;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.property.PropertyCopier;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.apache.ibatis.session.Configuration;
/**
* Cglib懒加载代理工厂
* @author Clinton Begin
*/
public class CglibProxyFactory implements ProxyFactory {
/**
* finalize 方法名
*/
private static final String FINALIZE_METHOD = "finalize";
/**
* writeReplace 方法名
*/
private static final String WRITE_REPLACE_METHOD = "writeReplace";
public CglibProxyFactory() {
//检查是否存在cglib的包
try {
Resources.classForName("net.sf.cglib.proxy.Enhancer");
} catch (Throwable e) {
throw new IllegalStateException("Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath.", e);
}
}
/**
*
* @param target 结果对象
* @param lazyLoader 用来表示需要懒加载的属性集,本质是一个HashMap
* @param configuration Mybatis全局配置信息
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return
*/
@Override
public Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List
JavassistProxyFactory
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor.loader.javassist;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.loader.AbstractEnhancedDeserializationProxy;
import org.apache.ibatis.executor.loader.AbstractSerialStateHolder;
import org.apache.ibatis.executor.loader.ResultLoaderMap;
import org.apache.ibatis.executor.loader.WriteReplaceInterface;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.property.PropertyCopier;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.apache.ibatis.session.Configuration;
/**
* Javassist代理工厂
* @author Eduardo Macarron
*/
public class JavassistProxyFactory implements org.apache.ibatis.executor.loader.ProxyFactory {
/**
* finalize 方法名
*/
private static final String FINALIZE_METHOD = "finalize";
/**
* writeReplace 方法名
*/
private static final String WRITE_REPLACE_METHOD = "writeReplace";
public JavassistProxyFactory() {
//检查是否存在javassist的包
try {
Resources.classForName("javassist.util.proxy.ProxyFactory");
} catch (Throwable e) {
throw new IllegalStateException("Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.", e);
}
}
/**
* 创建代理对象
* @param target 结果对象
* @param lazyLoader 用来表示需要懒加载的属性集,本质是一个HashMap
* @param configuration Mybatis全局配置信息
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 代理对象
*/
@Override
public Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
return EnhancedResultObjectProxyImpl.createProxy(target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}
/**
* 创建反序列化代理对象
* @param target 结果对象
* @param unloadedProperties 未加载的属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 反序列化代理对象
*/
public Object createDeserializationProxy(Object target, Map unloadedProperties, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
//创建结果对象代理对象
return EnhancedDeserializationProxyImpl.createProxy(target, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}
@Override
public void setProperties(Properties properties) {
// Not Implemented
}
/**
* 创建代理对象
* @param type 结果对象类型
* @param callback 增强结果对象代理实现类
* @param constructorArgTypes 构造函数参数类型数组
* @param constructorArgs 构造函数参数数组
* @return 代理对象
*/
static Object crateProxy(Class> type, MethodHandler callback, List> constructorArgTypes, List constructorArgs) {
//javassist的代理工厂
ProxyFactory enhancer = new ProxyFactory();
//设置需要创建子类的父类
enhancer.setSuperclass(type);
try {
//获取结果对象类型的WriteReplace方法
type.getDeclaredMethod(WRITE_REPLACE_METHOD);
// ObjectOutputStream will call writeReplace of objects returned by writeReplace
//如果可以打印出log
if (LogHolder.log.isDebugEnabled()) {
//打印log,通知WriteReplace方法在type找到了
LogHolder.log.debug(WRITE_REPLACE_METHOD + " method was found on bean " + type + ", make sure it returns this");
}
} catch (NoSuchMethodException e) {
//如果不存在WriteReplace方法时,让子类继承WriteReplaceInterface接口
enhancer.setInterfaces(new Class[]{WriteReplaceInterface.class});
} catch (SecurityException e) {
// nothing to do here
}
Object enhanced;
//将构造函数参数类型集合转换成构造函数参数类型数组
Class>[] typesArray = constructorArgTypes.toArray(new Class[constructorArgTypes.size()]);
//将构造函数参数集合转换成构造函数参数数组
Object[] valuesArray = constructorArgs.toArray(new Object[constructorArgs.size()]);
try {
//创建结果对象的代理对象并赋值给enhanced
enhanced = enhancer.create(typesArray, valuesArray);
} catch (Exception e) {
throw new ExecutorException("Error creating lazy proxy. Cause: " + e, e);
}
//定义一个拦截器。在调用目标方法时,Javassist会回调MethodHandler接口方法拦截,
//来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。
((Proxy) enhanced).setHandler(callback);
return enhanced;
}
/**
* 增强结果对象代理实现类
*/
private static class EnhancedResultObjectProxyImpl implements MethodHandler {
/**
* 结果对象类型
*/
private final Class> type;
/**
* 用来表示需要懒加载的属性集,本质是一个HashMap
*/
private final ResultLoaderMap lazyLoader;
/**
* 对应于configuration.isAggressiveLazyLoading();当开启时,任何方法的调用都会加载该对象的所有属性。
* 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。默认为false (在 3.4.1 及之前的版本默认值为 true)
*/
private final boolean aggressive;
/**
* 指定哪个对象的方法触发一次延迟加载。默认方法为:equals,clone,hashCode,toString
*/
private final Set lazyLoadTriggerMethods;
/**
* 对象工厂
*/
private final ObjectFactory objectFactory;
/**
* 构造函数参数类型数组
*/
private final List> constructorArgTypes;
/**
* 构造函数参数数组
*/
private final List constructorArgs;
/**
*
* @param type 结果对象类型
* @param lazyLoader 用来表示需要懒加载的属性集,本质是一个HashMap
* @param configuration Mybatis全局配置信息
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型数组
* @param constructorArgs 构造函数参数数组
*/
private EnhancedResultObjectProxyImpl(Class> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
this.type = type;
this.lazyLoader = lazyLoader;
// AggressiveLazyLoading: 当开启时,任何方法的调用都会加载该对象的所有属性。
// 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。默认为false (在 3.4.1 及之前的版本默认值为 true)
this.aggressive = configuration.isAggressiveLazyLoading();
//LazyLoadTriggerMethod:指定哪个对象的方法触发一次延迟加载。默认方法为:equals,clone,hashCode,toString
this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods();
this.objectFactory = objectFactory;
this.constructorArgTypes = constructorArgTypes;
this.constructorArgs = constructorArgs;
}
/**
* 创建代理对象
* @param target 结果对象
* @param lazyLoader 用来表示需要懒加载的属性集,本质是一个HashMap
* @param configuration Mybatis全局配置信息
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 代理对象
*/
public static Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
//获取结果对象类型
final Class> type = target.getClass();
//新建一个增强结果对象代理实现类对象
EnhancedResultObjectProxyImpl callback = new EnhancedResultObjectProxyImpl(type, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
//创建代理对象
Object enhanced = crateProxy(type, callback, constructorArgTypes, constructorArgs);
//将type 的属性值复制到enhanced中
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}
/**
* 拦截回调
* @param enhanced 由Javassist动态生成的代理类实例
* @param method 当前要调用的方法
* @param methodProxy JavaAssist获取的进程,是修改后的类方法
* @param args 参数值列表
* @return 从代理实例的方法调用返回的值
*/
@Override
public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
//获取当前要调用的方法名
final String methodName = method.getName();
try {
//同步加锁,防止在多线程情况下,重复加载结果对象属性
synchronized (lazyLoader) {
//如果当前要调用的方法名是WriteReplace
if (WRITE_REPLACE_METHOD.equals(methodName)) {
Object original;
//如果构造函数参数类型集合为空
if (constructorArgTypes.isEmpty()) {
//使用无参构造函数创建结果对象
original = objectFactory.create(type);
} else {
//使用对应constructorArgTypes的构造函数创建结果对象
original = objectFactory.create(type, constructorArgTypes, constructorArgs);
}
//将enhanced的属性值复制到original中
PropertyCopier.copyBeanProperties(type, enhanced, original);
//如果需要懒加载的属性集不是空集合
if (lazyLoader.size() > 0) {
//新建一个Javassist序列化状态持有者对象
return new JavassistSerialStateHolder(original, lazyLoader.getProperties(), objectFactory, constructorArgTypes, constructorArgs);
//如果没有需要懒加载的属性
} else {
//返回原始对象
return original;
}
////如果不是writeReplace方法
} else {
//如果需要懒加载的属性集不是空集合 且 当前要调用的方法名不是finalize
if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) {
//如果设置了任何方法的调用都会加载该对象的所有属性 或者 指定触发一次延迟加载的方法
if (aggressive || lazyLoadTriggerMethods.contains(methodName)) {
//执行对 加载器映射队列的所有元素 的懒加载查询
lazyLoader.loadAll();
//如是setter方法
} else if (PropertyNamer.isSetter(methodName)) {
//获取methodName对应的属性名
final String property = PropertyNamer.methodToProperty(methodName);
//移除该属性的懒加载器,因为调用该属性的setter方法就意味该属性重新赋值,所以不需要再加载
lazyLoader.remove(property);
//如果是getter方法
} else if (PropertyNamer.isGetter(methodName)) {
//获取methodName对应的属性名
final String property = PropertyNamer.methodToProperty(methodName);
//如果存在property对应的懒加载器
if (lazyLoader.hasLoader(property)) {
//执行对 property 的懒加载查询
lazyLoader.load(property);
}
}
}
}
}
//否则执行代理方法
return methodProxy.invoke(enhanced, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
/**
* 增强反序列代理接口实现类
*/
private static class EnhancedDeserializationProxyImpl extends AbstractEnhancedDeserializationProxy implements MethodHandler {
/**
*
* @param type 接口对象类型
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
*/
private EnhancedDeserializationProxyImpl(Class> type, Map unloadedProperties, ObjectFactory objectFactory,
List> constructorArgTypes, List constructorArgs) {
super(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}
/**
* 创建代理对象
* @param target 结果对象
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 代理对象
*/
public static Object createProxy(Object target, Map unloadedProperties, ObjectFactory objectFactory,
List> constructorArgTypes, List constructorArgs) {
//获取结果对象类
final Class> type = target.getClass();
//新建一个增强反序列化代理实现类对象
EnhancedDeserializationProxyImpl callback = new EnhancedDeserializationProxyImpl(type, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
//创建代理对象
Object enhanced = crateProxy(type, callback, constructorArgTypes, constructorArgs);
//将target的属性值复制到enhanced中
PropertyCopier.copyBeanProperties(type, target, enhanced);
return enhanced;
}
/**
* 拦截回调
* @param enhanced 由Javassist动态生成的代理类实例
* @param method 当前要调用的方法
* @param methodProxy JavaAssist获取的进程,是修改后的类方法
* @param args 参数值列表
* @return 从代理实例的方法调用返回的值
*/
@Override
public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
//执行AbstractEnhancedDeserializationProxy的invoke方法,得到代理类对象实例赋值给o
final Object o = super.invoke(enhanced, method, args);
//如果o是AbstractSerialStateHolder的子类,返回o;否则执行代理方法
return o instanceof AbstractSerialStateHolder ? o : methodProxy.invoke(o, args);
}
/**
* 新建一个序列化转换持有者对象
* @param userBean 结果对象
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 序列化转换持有者对象
*/
@Override
protected AbstractSerialStateHolder newSerialStateHolder(Object userBean, Map unloadedProperties, ObjectFactory objectFactory,
List> constructorArgTypes, List constructorArgs) {
//新建一个Javassist序列化状态持有者对象
return new JavassistSerialStateHolder(userBean, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
}
}
private static class LogHolder {
private static final Log log = LogFactory.getLog(JavassistProxyFactory.class);
}
}
AbstractEnhancedDeserializationProxy
/**
* Copyright 2009-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor.loader;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.property.PropertyCopier;
import org.apache.ibatis.reflection.property.PropertyNamer;
/**
* 抽象增强反序列化代理
* @author Clinton Begin
*/
public abstract class AbstractEnhancedDeserializationProxy {
/**
* finalize方法名
*/
protected static final String FINALIZE_METHOD = "finalize";
/**
* writeReplace 方法名
*/
protected static final String WRITE_REPLACE_METHOD = "writeReplace";
/**
* 结果对象类型
*/
private final Class> type;
/**
* 未加载属性集
*/
private final Map unloadedProperties;
/**
* 对象工厂
*/
private final ObjectFactory objectFactory;
/**
* 构造函数参数类型数组
*/
private final List> constructorArgTypes;
/**
* 构造函数参数对象
*/
private final List constructorArgs;
/**
* 正在重新加载属性锁
*/
private final Object reloadingPropertyLock;
/**
* 是否正在重新加载属性
*/
private boolean reloadingProperty;
/**
*
* @param type 结果对象类型
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
*/
protected AbstractEnhancedDeserializationProxy(Class> type, Map unloadedProperties,
ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
this.type = type;
this.unloadedProperties = unloadedProperties;
this.objectFactory = objectFactory;
this.constructorArgTypes = constructorArgTypes;
this.constructorArgs = constructorArgs;
this.reloadingPropertyLock = new Object();
this.reloadingProperty = false;
}
/**
* 拦截回调
* @param enhanced 代理类对象实例
* @param method 当前要调用的方法
* @param args 参数对象数组
* @return 代理类对象实例
*/
public final Object invoke(Object enhanced, Method method, Object[] args) throws Throwable {
//获取当前要调用的方法名
final String methodName = method.getName();
try {
//如果当前要调用的方法名是WriteReplace
if (WRITE_REPLACE_METHOD.equals(methodName)) {
final Object original;
//如果构造函数参数类型集合为空
if (constructorArgTypes.isEmpty()) {
//使用无参构造函数创建结果对象
original = objectFactory.create(type);
} else {
//使用对应constructorArgTypes的构造函数创建结果对象
original = objectFactory.create(type, constructorArgTypes, constructorArgs);
}
//将enhanced的属性值复制到original中
PropertyCopier.copyBeanProperties(type, enhanced, original);
//新建一个序列化转换持有者对象
return this.newSerialStateHolder(original, unloadedProperties, objectFactory, constructorArgTypes, constructorArgs);
} else {
//同步加锁,防止在多线程情况下,重复加载结果对象属性
synchronized (this.reloadingPropertyLock) {
//如果当前要调用的方法名不是WriteReplace 且 当前调用方法名是属性方法 且 不是正在重新加载属性
if (!FINALIZE_METHOD.equals(methodName) && PropertyNamer.isProperty(methodName) && !reloadingProperty) {
//取出methodName方法名的属性名
final String property = PropertyNamer.methodToProperty(methodName);
//将属性名转换成大写
final String propertyKey = property.toUpperCase(Locale.ENGLISH);
//如果proertypeKey属于未加载的属性集中的属性
if (unloadedProperties.containsKey(propertyKey)) {
//获取propertyKey对应的LoadPair对象
final ResultLoaderMap.LoadPair loadPair = unloadedProperties.remove(propertyKey);
//如果loadPair不为null
if (loadPair != null) {
try {
//设置正在重新加载属性为true
reloadingProperty = true;
//执行懒加载查询,获取数据并且赋值到enhanced
loadPair.load(enhanced);
} finally {
//还原设置正在重新加载属性为false
reloadingProperty = false;
}
} else {
/* I'm not sure if this case can really happen or is just in tests -
* we have an unread property but no loadPair to load it.
* 译文:
* 我不确定这种情况下能发生或只是在测试中 - 我们有一个未加载的属性但是没有LoadPair对象去加载它
* */
//抛出异常
throw new ExecutorException("An attempt has been made to read a not loaded lazy property '"
+ property + "' of a disconnected object");
}
}
}
return enhanced;
}
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
/**
* 新建一个序列化转换持有者对象
* @param userBean 结果对象
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 序列化转换持有者对象
*/
protected abstract AbstractSerialStateHolder newSerialStateHolder(
Object userBean,
Map unloadedProperties,
ObjectFactory objectFactory,
List> constructorArgTypes,
List constructorArgs);
}
AbstractSerialStateHolder
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor.loader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamException;
import java.io.StreamCorruptedException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.reflection.factory.ObjectFactory;
/**
* 抽象序列化转换持有者
*
* Externalizable:继承Serializable接口,可完成部分属性的序列化
*
* @author Eduardo Macarron
* @author Franta Mejta
*/
public abstract class AbstractSerialStateHolder implements Externalizable {
private static final long serialVersionUID = 8940388717901644661L;
private static final ThreadLocal stream = new ThreadLocal<>();
private byte[] userBeanBytes = new byte[0];
/**
* 结果对象
*/
private Object userBean;
/**
* 未加载的属性集
*
* LoadPair:对于单个属性懒加载信息的封装,最重要的就是其load方法用来加载属性
*
*/
private Map unloadedProperties;
/**
* 对象工厂
*/
private ObjectFactory objectFactory;
/**
* 构造函数参数类型数组
*/
private Class>[] constructorArgTypes;
/**
* 构造函数参数数组
*/
private Object[] constructorArgs;
public AbstractSerialStateHolder() {
}
/**
*
* @param userBean 结果对象
* @param unloadedProperties 未加载的属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
*/
public AbstractSerialStateHolder(
final Object userBean,
final Map unloadedProperties,
final ObjectFactory objectFactory,
List> constructorArgTypes,
List constructorArgs) {
this.userBean = userBean;
this.unloadedProperties = new HashMap<>(unloadedProperties);
this.objectFactory = objectFactory;
//将构造函数参数类型集合转换成构造函数参数类型数组
this.constructorArgTypes = constructorArgTypes.toArray(new Class>[constructorArgTypes.size()]);
//将构造函数参数集合转换成构造函数参数数组
this.constructorArgs = constructorArgs.toArray(new Object[constructorArgs.size()]);
}
/**
* 序列化
* @param out 对象输出流
*/
@Override
public final void writeExternal(final ObjectOutput out) throws IOException {
//定义表示第一轮标记,设置为false
boolean firstRound = false;
//新建一个字节数组输出流
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
//获取对象输出流
ObjectOutputStream os = stream.get();
//如果os为null
if (os == null) {
//新建一个对象输出流对象装饰baos
os = new ObjectOutputStream(baos);
//将第一轮标记设置为true
firstRound = true;
//将输出流添加到stream中
stream.set(os);
}
//将结果对象写进对象流
os.writeObject(this.userBean);
//将未加载属性集写进对象流
os.writeObject(this.unloadedProperties);
//将对象工厂写进对象流
os.writeObject(this.objectFactory);
//将构造函数参数类型数组写进对象流
os.writeObject(this.constructorArgTypes);
//将构造函数参数数组写进对象流
os.writeObject(this.constructorArgs);
//取出字节数组
final byte[] bytes = baos.toByteArray();
//将字节数组写进out
out.writeObject(bytes);
//如果是第一轮
if (firstRound) {
//移除存放在stream的输出流
stream.remove();
}
}
/**
* 反序列化
* @param in 对象输入流
*/
@Override
public final void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
//读取流中的对象
final Object data = in.readObject();
//如果data是数组
if (data.getClass().isArray()) {
//将data强转成byte[]赋值给userBeanBytes
this.userBeanBytes = (byte[]) data;
} else {
//将data赋值给userBean
this.userBean = data;
}
}
@SuppressWarnings("unchecked")
protected final Object readResolve() throws ObjectStreamException {
/* Second run */
//如果userBean不为null且userBeanBytes为空数组
if (this.userBean != null && this.userBeanBytes.length == 0) {
//直接返回userBena
return this.userBean;
}
//新建一个反序列化对象白名单控制输入流对象对userBeanBytes进行解析
/* First run */
try (ObjectInputStream in = new LookAheadObjectInputStream(new ByteArrayInputStream(this.userBeanBytes))) {
//获取结果对象
this.userBean = in.readObject();
//获取未加载的属性集
this.unloadedProperties = (Map) in.readObject();
//获取对象工厂
this.objectFactory = (ObjectFactory) in.readObject();
//获取构造函数参数类型数组
this.constructorArgTypes = (Class>[]) in.readObject();
//获取构造函数参数数组
this.constructorArgs = (Object[]) in.readObject();
} catch (final IOException ex) {
throw (ObjectStreamException) new StreamCorruptedException().initCause(ex);
} catch (final ClassNotFoundException ex) {
throw (ObjectStreamException) new InvalidClassException(ex.getLocalizedMessage()).initCause(ex);
}
//将未加载的属性集添加到一个新的HashMap中
final Map arrayProps = new HashMap<>(this.unloadedProperties);
//将构造函数参数类型数组添加到新的ArrayList中
final List> arrayTypes = Arrays.asList(this.constructorArgTypes);
//将构造函数参数数组添加到新的ArrayList中
final List arrayValues = Arrays.asList(this.constructorArgs);
//创建反序列代理对象
return this.createDeserializationProxy(userBean, arrayProps, objectFactory, arrayTypes, arrayValues);
}
/**
* 创建反序列代理对象
* @param target 结果对象
* @param unloadedProperties 未加载属性集
* @param objectFactory 对象工厂
* @param constructorArgTypes 构造函数参数类型集合
* @param constructorArgs 构造函数参数集合
* @return 反序列代理对象
*/
protected abstract Object createDeserializationProxy(Object target, Map unloadedProperties, ObjectFactory objectFactory,
List> constructorArgTypes, List constructorArgs);
/**
* 反序列化对象白名单控制输入流
*/
private static class LookAheadObjectInputStream extends ObjectInputStream {
/**
* 黑名单类列表
*/
private static final List blacklist = Arrays.asList(
"org.apache.commons.beanutils.BeanComparator",
"org.apache.commons.collections.functors.InvokerTransformer",
"org.apache.commons.collections.functors.InstantiateTransformer",
"org.apache.commons.collections4.functors.InvokerTransformer",
"org.apache.commons.collections4.functors.InstantiateTransformer",
"org.codehaus.groovy.runtime.ConvertedClosure",
"org.codehaus.groovy.runtime.MethodClosure",
"org.springframework.beans.factory.ObjectFactory",
"org.springframework.transaction.jta.JtaTransactionManager",
"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
public LookAheadObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
//获取desc的包名+类名
String className = desc.getName();
//如果className存在在黑名单类列表中,表示可能有黑客在反序列的时候篡改了字节数据
if (blacklist.contains(className)) {
//抛出异常
throw new InvalidClassException(className, "Deserialization is not allowed for security reasons. "
+ "It is strongly recommended to configure the deserialization filter provided by JDK. "
+ "See http://openjdk.java.net/jeps/290 for the details.");
}
return super.resolveClass(desc);
}
}
}
PropertyCopier
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.property;
import java.lang.reflect.Field;
import org.apache.ibatis.reflection.Reflector;
/**
* 属性复制器
* @author Clinton Begin
*/
public final class PropertyCopier {
private PropertyCopier() {
// Prevent Instantiation of Static Class
}
/**
* 将{@code sourceBean} 的属性值复制到{@code destinationBean}中
* @param type {@code sourceBean}和{@code destinationBean} 都同时继承的类
* @param sourceBean 原对象
* @param destinationBean 目标对象
*/
public static void copyBeanProperties(Class> type, Object sourceBean, Object destinationBean) {
//然后type充当parent
Class> parent = type;
//只要parent不为null,继续循环
while (parent != null) {
//获取类中的所有Field
final Field[] fields = parent.getDeclaredFields();
//遍历所有Field
for (Field field : fields) {
try {
try {
//获取sourceBean的field属性值赋值到destinationBean的Field属性中
field.set(destinationBean, field.get(sourceBean));
} catch (IllegalAccessException e) {
//如果从java安全管理器中获取suppressAccessChecks反射权限是存在的
if (Reflector.canControlMemberAccessible()) {
//设置属性为可访问
field.setAccessible(true);
//获取sourceBean的field属性值赋值到destinationBean的Field属性中
field.set(destinationBean, field.get(sourceBean));
} else {
//抛出无权限访问异常
throw e;
}
}
} catch (Exception e) {
// Nothing useful to do, will only fail on final fields, which will be ignored.
}
}
//获取parent的父类重新赋值给parent
parent = parent.getSuperclass();
}
}
}
转:http://stackoverflow.com/questions/18145774/eclipse-an-error-occurred-while-filtering-resources
maven报错:
maven An error occurred while filtering resources
Maven -> Update Proje
在SVN服务控制台打开资源库“SVN无法读取current” ---摘自网络 写道 SVN无法读取current修复方法 Can't read file : End of file found
文件:repository/db/txn_current、repository/db/current
其中current记录当前最新版本号,txn_current记录版本库中版本