jdk的动态代理:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;
/**
* 使用代理模式,使用各种代理的组合
*/
public class Tank implements Moveable {
@Override
public void move() {
System.out.println("Tank moveing clacalacala....");
try{
Thread.sleep(new Random().nextInt(3000));
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Tank tank = new Tank();
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Moveable m = (Moveable)Proxy.newProxyInstance(Tank.class.getClassLoader(),
new Class[]{Moveable.class},
new LogHandler(tank)
);
m.move();
}
}
class LogHandler implements InvocationHandler{
Tank tank;
public LogHandler(Tank tank) {
this.tank = tank;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method "+method.getName()+" start...");
Object o = method.invoke(tank, args);
System.out.println("method "+method.getName()+" end...");
return o;
}
}
interface Moveable {
void move();
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
final class $Proxy0 extends Proxy implements Moveable {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(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 void move() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 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"));
m3 = Class.forName("com.qqlindy.proxy.v5.Moveable").getMethod("move");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
jdk的动态代理执行过程:

client 相当于main 调用Proxy的Proxy.newProxyInstance生成Proxy0这个类,生成了这个对象,往里面传了个参数InvocationHandler。接下来调用Proxy0这个类,生成了这个对象,往里面传了个参数InvocationHandler。接下来调用Proxy0这个类,生成了这个对象,往里面传了个参数InvocationHandler。接下来调用Proxy0的这个move方法。move方法调用InvocationHandler的invoke方法。这里面执行before,然后调用Tank的move方法,再执行after.
通过ASM生成动态代理类。

public class Proxy implements java.io.Serializable {
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
private byte[] generateClassFile() {
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
加入move方法:
Iterator var11 = this.proxyMethods.values().iterator();
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}
Iterator var15;
try {
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();
while(var15.hasNext()) {
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
this.methods.add(var16.generateMethod()); //调用add方法
}
}
this.methods.add(this.generateStaticInitializer());
} catch (IOException var10) {
throw new InternalError("unexpected I/O Exception", var10);
}
上面add方法本质上调用:所以jdk的动态代理是由ASM操作的。 直接操作二进制操作码。

所以了用了ASM之后,Java才可以被称为动态语言。所谓的动态语言就是指在运行的时候,动态改变类的属性和方法。动态添加,动态删除。 (而反射只能读出来,不能改。)。 JDK反射生成代理必须面向接口,这是由JDK Proxy的内部实现决定的 ,只有实现了接口, 代理类内部才知道内部需要写哪些方法,不然不知道。
还有一种方式生成动态代理: Instrument , 调琴。 Java自带的方式: 钩子函数, 是一个拦截器, 每一个Class load到内存中,会拦住这个Class. 在拦截的时候可以进行定制。
cglib: code generate 代码生成。cglib底层用的也是ASM,Spring用的也是ASM
下面例子如果Tank类是Final,cglib是生产不了代理的。 asm可以。直接操作二进制码。 cglib底层用的也是asm. Spring用的也是asm.
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.Random;
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer(); //Enhancer增强器
enhancer.setSuperclass(Tank.class);
enhancer.setCallback(new TimeMethodInterceptor()); //TimeMethodInterceptor相当于JDM动态代理的InvocationHandler
Tank tank = (Tank) enhancer.create(); //动态代理的对象生成
tank.move();
}
}
class TimeMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(o.getClass().getSuperclass().getName());
System.out.println("before");
Object result = null;
result = methodProxy.invokeSuper(o, objects); //调用原来的方法
System.out.println("after");
return result;
}
}
class Tank{ //如果Tank类是Final,cglib是生产不了代理的。 asm可以。直接操作二进制码。 cglib底层用的也是asm. Spring用的也是asm.
public void move(){
System.out.println("Tank is move....");
try{
Thread.sleep(new Random().nextInt(3000));
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
2661

被折叠的 条评论
为什么被折叠?



