大家好,又见面了,我是你们的朋友全栈君。
BeanCopier 实现属性拷贝的主要代码:
BeanCopier beanCopier = BeanCopier.create(dad.getClass(), dadly.getClass(), false);
beanCopier.copy(dad, dadly, null);
查看BeanCopier源码可知:
abstract public class BeanCopier
{
private static final BeanCopierKey KEY_FACTORY =
(BeanCopierKey)KeyFactory.create(BeanCopierKey.class);
private static final Type CONVERTER =
TypeUtils.parseType("net.sf.cglib.core.Converter");
private static final Type BEAN_COPIER =
TypeUtils.parseType("net.sf.cglib.beans.BeanCopier");
private static final Signature COPY =
new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER });
private static final Signature CONVERT =
TypeUtils.parseSignature("Object convert(Object, Class, Object)");
BeanCopier为抽象类,并且:
代码语言:javascript复制abstract public void copy(Object from, Object to, Converter converter);
copy为抽象方法,在cglib的包里我们找不到 BeanCopier的实现类。
由此我们可以根据此行代码:
BeanCopier beanCopier = BeanCopier.create(dad.getClass(), dadly.getClass(), false);
并且:
代码语言:javascript复制public static BeanCopier create(Class source, Class target, boolean useConverter) {
Generator gen = new Generator();
gen.setSource(source);
gen.setTarget(target);
gen.setUseConverter(useConverter);
return gen.create();
}
public static class Generator extends AbstractClassGenerator {
....
public BeanCopier create() {
Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter);
return (BeanCopier)super.create(key);
}
...
}
由此可知:
beanCopier 的实际创建工作是由AbstractClassGenerator类的create(Class type)方法完成的,如下是此方法源码:
代码语言:javascript复制 protected Object create(Object key) {
try {
Class gen = null;
synchronized (source) {
ClassLoader loader = getClassLoader();
Map cache2 = null;
cache2 = (Map)source.cache.get(loader);
if (cache2 == null) {
cache2 = new HashMap();
cache2.put(NAME_KEY, new HashSet());
source.cache.put(loader, cache2);
} else if (useCache) {
Reference ref = (Reference)cache2.get(key);
gen = (Class) (( ref == null ) ? null : ref.get());
}
if (gen == null) {
Object save = CURRENT.get();
CURRENT.set(this);
try {
this.key = key;
if (attemptLoad) {
try {
gen = loader.loadClass(getClassName());
} catch (ClassNotFoundException e) {
// ignore
}
}
if (gen == null) {
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
getClassNameCache(loader).add(className);
gen = ReflectUtils.defineClass(className, b, loader);
}
if (useCache) {
cache2.put(key, new WeakReference(gen));
}
return firstInstance(gen);
} finally {
CURRENT.set(save);
}
}
}
return firstInstance(gen);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
熟悉cglib动态代理源码的都知道,此处代码就是cglib操作字节码生成动态代理类的主要实现方法。
所以beanCopier 实际上是BeanCopier的代理类,该代理类实现了 copy()方法,即如何复制相同名称的属性。
以下是生成的动态代理类:
代码语言:javascript复制// Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov Date: 2013/10/17 22:01:37
// Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version!
// Decompiler options: packimports(3)
// Source File Name: <generated>
package proxy;
import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.core.Converter;
// Referenced classes of package proxy:
// Dadly, Dad
public class Dadly$$BeanCopierByCGLIB$$a6acdbb5 extends BeanCopier
{
public void copy(Object obj, Object obj1, Converter converter)
{
(Dadly)obj1;
(Dad)obj;
JVM INSTR dup2 ;
getAge();
setAge();
JVM INSTR dup2 ;
getName();
setName();
}
public Dadly$$BeanCopierByCGLIB$$a6acdbb5()
{
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。