以前值是读过一遍jdk和cglib的代理,时间长了,都忘记入口在哪里了,值是记得其中的一些重点了,今天写一篇博客,当作是笔记。和以前一样,关键代码,我会用红色标记出来。
首先,先列出我的jdk代理对象和测试代码:
package com.example.gof.proxy;
/**
* 买车接口
*/
public interface BuyCard {
void buycard();
}
package com.example.gof.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class BuyCardDynamicProxy implements InvocationHandler {
private Object object;
public BuyCardDynamicProxy(final Object object) {
this.object = object;
}
/\*\*
\* 代理回调的方法,反编译后可以看到调用的是这段代码:super.h.invoke(this, m3, null);
\* m3 = Class.forName("com.example.gof.proxy.BuyCard").getMethod("buycard", new Class\[0\]);
\* @param proxy 代理
\* @param method 代理调用的而方法
\* @param args 调用的方法的参数
\* @return
\* @throws Throwable
\*/
@Override
public Object invoke(Object proxy, Method method, Object\[\] args) throws Throwable {
System.out.println("动态代理,买车前");
Object res= method.invoke(object,args);
System.out.println("动态代理,洗刷刷");
return res;
}
}
package com.example.gof.proxy;
import com.example.gof.proxy.impl.BuyCardImpl;
import sun.misc.ProxyGenerator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;
public class TestBuyCardDynamicProxy {
public static void main(String[] args) throws IOException {
BuyCard buyCard = new BuyCardImpl();
BuyCard buyCardProxy = (BuyCard) Proxy.newProxyInstance(BuyCard.class.getClassLoader(),
new Class[]{BuyCard.class}, new BuyCardDynamicProxy(buyCard));
buyCardProxy.buycard();
//下面这段是用于生成字节码分析的
// byte[] classFile= ProxyGenerator.generateProxyClass("$Proxy", new Class>[]{BuyCard.class});
// File file=new File("D:\\java\\GoF\\src\\main\\java\\com\\example\\gof\\proxy/$Proxy.class");
// FileOutputStream os=new FileOutputStream(file);
// os.write(classFile);
// os.flush();
// os.close();
}
}
跟踪进去,查看 Proxy.newProxyInstance(BuyCard.class.getClassLoader() 这个方法,代码如下:
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
* 返回一个代理类实例,用于调用响应的接口方法
*
{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
* {@code Proxy.getProxyClass} does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
* @throws SecurityException if a security manager, s, is present
* and any of the following conditions is met:
*
final Class<?>\[\] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/\*
\* Look up or generate the designated proxy class.
\* 查找或者生成一个代理对象
\*/
Class<?> cl = getProxyClass0(loader, intfs);
/\*
\* Invoke its constructor with the designated invocation handler.
\*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object\[\]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
/\*\*
\* a cache of proxy classes
\*/
private static final WeakCache<ClassLoader, Class<?>\[\], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/\*\*
\* Generate a proxy class. Must call the checkProxyAccess method
\* to perform permission checks before calling this.
\*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
上面这个代码当初看了很久,怎么到proxyClassCache.get(loader, interfaces); 就已经生成了代理对象呢。后来百度下,才知道proxyClassCache9 这个对象调用构造参数时候,就生成了二进制文件,核心代码也在这里。继续往下看
/\*\*
\* A factory function that generates, defines and returns the proxy class given
\* the ClassLoader and array of interfaces.
\* 一个工厂函数,它生成、定义并返回给定类加载器和接口数组的代理类。
\*/
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>\[\], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>\[\] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/\*
\* Verify that the class loader resolves the name of this
\* interface to the same Class object.
\*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/\*
\* Verify that the Class object actually represents an
\* interface.
\*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/\*
\* Verify that this interface is not a duplicate.
\*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/\*
\* Record the package of a non-public proxy interface so that the
\* proxy class will be defined in the same package. Verify that
\* all non-public proxy interfaces are in the same package.
\*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY\_PACKAGE + ".";
}
/\*
\* Choose a name for the proxy class to generate.
\*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/\*
\* Generate the specified proxy class.
\* 生成代理对象
\*/
byte\[\] proxyClassFile = ProxyGenerator.generateProxyClass( //生成二进制字节码
proxyName, interfaces, accessFlags);
try {
//加载到jvm里,返回代理对象
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/\*
\* A ClassFormatError here means that (barring bugs in the
\* proxy class generation code) there was some other
\* invalid aspect of the arguments supplied to the proxy
\* class creation (such as virtual machine limitations
\* exceeded).
\*/
throw new IllegalArgumentException(e.toString());
}
}
}
继续跟进生成二进制字节码的方法:ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags)
public static byte[] generateProxyClass(final String var0, Class>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
Files.write(var2, var4, new OpenOption\[0\]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
由上面可以看见,核心代码,就是生成了二进制字节码文件Files.write(var2, var4, new OpenOption[0]);
为什么我们看不见呢,那是因为被删除了,可以手动生成这个二进制文件(.class后缀的),也就是上面的那段测试代码的例子。
下面是二进制字节码的文件内容:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.example.gof.proxy.BuyCard;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy extends Proxy implements BuyCard {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object\[\]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object\[\])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void buycard() throws {
try {
super.h.invoke(this, m3, (Object\[\])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object\[\])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.example.gof.proxy.BuyCard").getMethod("buycard");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
从上面可以看到,除了自定义的buycard() 方法外,还有toString()、equals()、hashCode() 三个方法。这三个方法是Object 的方法,每个接口、类都会从Object继承这三个方法。当调用buycard()的时候,可以看到调用的是super.h.invoke(xxx) 这样调用的。这里的h,就是我们自定义的,继承了InvocationHandler的类:BuyCardDynamicProxy。
至于invoke方式是怎么调用的,在另外一篇博客https://www.cnblogs.com/drafire/p/9637349.html 继续解析
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面看下cglib的代码解读,依然是先贴出测试代码
public class BuyCardCglibProxy implements MethodInterceptor {
private Object target;
public Object getInstance(final Object target) {
this.target = target;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object\[\] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib动态代理前");
//这里使用的是methodProxy.invokeSuper,而不是method.invoke
//代理类调用父类的方法
Object res= methodProxy.invokeSuper(o,objects);
System.out.println("cglib动态代理后");
return res;
}
}
package com.example.gof.proxy;
import com.example.gof.proxy.impl.BuyCardImpl;
import org.springframework.cglib.core.DebuggingClassWriter;
public class TestBuyCardCglibProxy {
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, TestBuyCardCglibProxy.class.getClass().getResource("/").getPath() );
BuyCard buyCard=new BuyCardImpl();
BuyCardCglibProxy proxy=new BuyCardCglibProxy();
BuyCardImpl impl= (BuyCardImpl)proxy.getInstance(buyCard);
impl.buycard();
}
}
关键代码在:enhancer.create() 这个方法,跟踪进去,代码如下:
public Object create() {
this.classOnly = false;
this.argumentTypes = null;
return this.createHelper();
}
private Object createHelper() {
this.preValidate();
Object key = KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter == ALL_ZERO ? null : new WeakCacheKey(this.filter), this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
protected Object create(Object key) {
try {
ClassLoader loader = this.getClassLoader(); //获取加载器
Map
//从缓存中读取
AbstractClassGenerator.ClassLoaderData data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
if (data == null) { //如果缓存没有对应的数据
Class var5 = AbstractClassGenerator.class;
synchronized(AbstractClassGenerator.class) {
cache = CACHE;
data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
if (data == null) {
Map
data = new AbstractClassGenerator.ClassLoaderData(loader); //生成二进制字节码
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
Object obj = data.get(this, this.getUseCache());
//生成代理对象
return obj instanceof Class ? this.firstInstance((Class)obj) : this.nextInstance(obj);
} catch (RuntimeException var9) {
throw var9;
} catch (Error var10) {
throw var10;
} catch (Exception var11) {
throw new CodeGenerationException(var11);
}
}
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
} else {
this.classLoader = new WeakReference(classLoader);
Function
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this); //核心代码
return gen.wrapCachedClass(klass);
}
};
this.generatedClasses = new LoadingCache(GET_KEY, load);
}
}
protected Class generate(AbstractClassGenerator.ClassLoaderData data) {
Object save = CURRENT.get();
CURRENT.set(this);
Class var8;
try {
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null while trying to define class " + this.getClassName() + ". It seems that the loader has been expired from a weak reference somehow. Please file an issue at cglib's issue tracker.");
}
String className;
synchronized(classLoader) {
className = this.generateClassName(data.getUniqueNamePredicate());
data.reserveName(className);
this.setClassName(className);
}
Class gen;
if (this.attemptLoad) {
try {
gen = classLoader.loadClass(this.getClassName());
Class var25 = gen;
return var25;
} catch (ClassNotFoundException var20) {
;
}
}
byte\[\] b = this.strategy.generate(this); //核心代码
className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = this.getProtectionDomain();
synchronized(classLoader) {
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
var8 = gen;
} catch (RuntimeException var21) {
throw var21;
} catch (Error var22) {
throw var22;
} catch (Exception var23) {
throw new CodeGenerationException(var23);
} finally {
CURRENT.set(save);
}
return var8;
}
//org\springframework\spring-core\5.0.8.RELEASE\spring-core-5.0.8.RELEASE.jar!\org\springframework\cglib\core\DefaultGeneratorStrategy.class
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = this.getClassVisitor(); //从这里的源代码,可以看出,底层是使用asm包的
this.transform(cg).generateClass(cw);
return this.transform(cw.toByteArray());
}
//org\springframework\spring-core\5.0.8.RELEASE\spring-core-5.0.8.RELEASE.jar!\org\springframework\cglib\core\KeyFactory.class
public void generateClass(ClassVisitor v) {
ClassEmitter ce = new ClassEmitter(v);
Method newInstance = ReflectUtils.findNewInstance(this.keyInterface);
if (!newInstance.getReturnType().equals(Object.class)) {
throw new IllegalArgumentException("newInstance method must return Object");
} else {
Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
ce.begin_class(46, 1, this.getClassName(), KeyFactory.KEY_FACTORY, new Type[]{Type.getType(this.keyInterface)}, "
EmitUtils.null_constructor(ce);
EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
int seed = 0;
CodeEmitter e = ce.begin_method(1, TypeUtils.parseConstructor(parameterTypes), (Type[])null);
e.load_this();
e.super_invoke_constructor();
e.load_this();
List
int i;
for(i = 0; i < parameterTypes.length; ++i) {
Type parameterType = parameterTypes\[i\];
Type fieldType = parameterType;
Iterator var11;
FieldTypeCustomizer customizer;
for(var11 = fieldTypeCustomizers.iterator(); var11.hasNext(); fieldType = customizer.getOutType(i, fieldType)) {
customizer = (FieldTypeCustomizer)var11.next();
}
seed += fieldType.hashCode();
ce.declare\_field(18, this.getFieldName(i), fieldType, (Object)null);
e.dup();
e.load\_arg(i);
var11 = fieldTypeCustomizers.iterator();
while(var11.hasNext()) {
customizer = (FieldTypeCustomizer)var11.next();
customizer.customize(e, i, parameterType);
}
e.putfield(this.getFieldName(i));
}
e.return\_value();
e.end\_method();
e = ce.begin\_method(1, KeyFactory.HASH\_CODE, (Type\[\])null);
i = this.constant != 0 ? this.constant : KeyFactory.PRIMES\[Math.abs(seed) % KeyFactory.PRIMES.length\];
int hm = this.multiplier != 0 ? this.multiplier : KeyFactory.PRIMES\[Math.abs(seed \* 13) % KeyFactory.PRIMES.length\];
e.push(i);
for(int i = 0; i < parameterTypes.length; ++i) {
e.load\_this();
e.getfield(this.getFieldName(i));
EmitUtils.hash\_code(e, parameterTypes\[i\], hm, this.customizers);
}
e.return\_value();
e.end\_method();
e = ce.begin\_method(1, KeyFactory.EQUALS, (Type\[\])null);
Label fail = e.make\_label();
e.load\_arg(0);
e.instance\_of\_this();
e.if\_jump(153, fail);
int i;
for(i = 0; i < parameterTypes.length; ++i) {
e.load\_this();
e.getfield(this.getFieldName(i));
e.load\_arg(0);
e.checkcast\_this();
e.getfield(this.getFieldName(i));
EmitUtils.not\_equals(e, parameterTypes\[i\], fail, this.customizers);
}
e.push(1);
e.return\_value();
e.mark(fail);
e.push(0);
e.return\_value();
e.end\_method();
e = ce.begin\_method(1, KeyFactory.TO\_STRING, (Type\[\])null);
e.new\_instance(Constants.TYPE\_STRING\_BUFFER);
e.dup();
e.invoke\_constructor(Constants.TYPE\_STRING\_BUFFER);
for(i = 0; i < parameterTypes.length; ++i) {
if (i > 0) {
e.push(", ");
e.invoke\_virtual(Constants.TYPE\_STRING\_BUFFER, KeyFactory.APPEND\_STRING);
}
e.load\_this();
e.getfield(this.getFieldName(i));
EmitUtils.append\_string(e, parameterTypes\[i\], EmitUtils.DEFAULT\_DELIMITERS, this.customizers);
}
e.invoke\_virtual(Constants.TYPE\_STRING\_BUFFER, KeyFactory.TO\_STRING);
e.return\_value();
e.end\_method();
ce.end\_class();
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章