引入:今天工作中同事使用了Java8 Lists.partition 函数来批量更新/查询数据,架构组在mybatis插件扩展了mybatis#Interceptor 方法,具体实现拦截网上有大量资料可以查询下,这里就不引入介绍,连接器中使用 SerializationUtils.clone((Serializable) originParameter); 方法,来序列号param 对象,在对象复制的时候Lists.partition后得到的list 是一个Partition对象,该对象是继承了AbstractList 完成list 切分的。
我们看下Lists.partition源码:
public static <T> List<List<T>> partition(List<T> list, int size) {
Preconditions.checkNotNull(list);
Preconditions.checkArgument(size > 0);
return (List)(list instanceof RandomAccess ? new Lists.RandomAccessPartition(list, size) : new Lists.Partition(list, size));
}
private static class Partition<T> extends AbstractList<List<T>> {
final List<T> list;
final int size;
Partition(List<T> list, int size) {
this.list = list;
this.size = size;
}
public List<T> get(int index) {
Preconditions.checkElementIndex(index, this.size());
int start = index * this.size;
int end = Math.min(start + this.size, this.list.size());
return this.list.subList(start, end);
}
public int size() {
return IntMath.divide(this.list.size(), this.size, RoundingMode.CEILING);
}
public boolean isEmpty() {
return this.list.isEmpty();
}
}
看下对象Partition list对象属于内部类,没实现implements Serializable接口导致序列号失败
错误提示:
Caused by: org.apache.commons.lang3.SerializationException: java.io.NotSerializableException: java.util.ArrayList$SubList
at org.apache.commons.lang3.SerializationUtils.serialize(SerializationUtils.java:273) ~[commons-lang3-3.12.0.jar:3.12.0]
at org.apache.commons.lang3.SerializationUtils.serialize(SerializationUtils.java:248) ~[commons-lang3-3.12.0.jar:3.12.0]
at org.apache.commons.lang3.SerializationUtils.clone(SerializationUtils.java:138) ~[commons-lang3-3.12.0.jar:3.12.0]
at com.txxy.cloud.starter.druid.interceptor.CipherInterceptor.intercept(CipherInterceptor.java:92) ~[txxy-cloud-starter-druid-1.8.0-SNAPSHOT.jar:1.8.0-SNAPSHOT]
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) ~[mybatis-3.5.5.jar:3.5.5]
at com.sun.proxy.$Proxy466.update(Unknown Source) ~[?:?]
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:184) ~[mybatis-3.5.5.jar:3.5.5]
at sun.reflect.GeneratedMethodAccessor1471.invoke(Unknown Source) ~[?:?]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_212]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_212]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ~[mybatis-spring-2.0.5.jar:2.0.5]
正文:
浅复制
浅层复制: 被复制的对象的所有成员属性都有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
换言之,浅层复制仅仅复制所考虑的对象(对象属性、数据),而不复制它所引用的对象(对象地址)。
深复制
深层复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。
换言之,深层复制要复制的对象引用的对象(对象属性、数据)都复制一遍。
2.深拷贝实现起来也比较简单,只需要对对象中的对象再次进行clone操作:
commons-lang-2.6.jar
例如:Object obj = SerializationUtils.clone( objectFrom )
源码:
/**
* <p>Deep clone an {@code Object} using serialization.</p>
*
* <p>This is many times slower than writing clone methods by hand
* on all objects in your object graph. However, for complex object
* graphs, or for those that don't support deep cloning this can
* be a simple alternative implementation. Of course all the objects
* must be {@code Serializable}.</p>
*
* @param <T> the type of the object involved
* @param object the {@code Serializable} object to clone
* @return the cloned object
* @throws SerializationException (runtime) if the serialization fails
*/
public static <T extends Serializable> T clone(final T object) {
if (object == null) {
return null;
}
final byte[] objectData = serialize(object);
final ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
try (ClassLoaderAwareObjectInputStream in = new ClassLoaderAwareObjectInputStream(bais,
object.getClass().getClassLoader())) {
/*
* when we serialize and deserialize an object,
* it is reasonable to assume the deserialized object
* is of the same type as the original serialized object
*/
@SuppressWarnings("unchecked") // see above
final T readObject = (T) in.readObject();
return readObject;
} catch (final ClassNotFoundException ex) {
throw new SerializationException("ClassNotFoundException while reading cloned object data", ex);
} catch (final IOException ex) {
throw new SerializationException("IOException while reading or closing cloned object data", ex);
}
}
笔记就介绍这里了~~