动态代理 (JDK 动态代理)
动态代理: 代理类在程序运行时被创建,这种代理方式称为动态代理
动态代理实现有两种方式,JDK 动态代理和 CGlib 动态代理,本文介绍JDK 动态代理
JDK 动态代理:创建动态代理类,实现 InvocationHandler 接口,重写 invoke 方法,在 invoke 方法中通过反射调用被代理类的方法,实现代理。jdk 动态代理只能代理接口,即只能代理接口的实现类
JDK 动态代理示例代码
定义一个接口
package com.jdkdynamicproxy.service;
public interface Subject {
void proxyMethod();
}
被代理类,实现接口
package com.jdkdynamicproxy.service.impl;
import com.jdkdynamicproxy.service.Subject;
/**
* 被代理类
* @author Administrator
*/
public class AgentTarget implements Subject {
@Override
public void proxyMethod() {
System.out.println("被代理的方法执行了");
}
}
动态代理类,实现 InvocationHandler 接口
package com.jdkdynamicproxy.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.jdkdynamicproxy.service.impl.AgentTarget;
/**
* 动态代理类,实现 InvocationHandler接口
* @author Administrator
*/
public class JdkDynamicProxySubject implements InvocationHandler {
private AgentTarget agentTarget;
public JdkDynamicProxySubject(AgentTarget agentTarget) {
this.agentTarget = agentTarget;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理逻辑
System.out.println("before");
Object res = null;
try {
//用反射调用被代理类的方法
res = method.invoke(agentTarget, args);
}catch (Exception ex){
System.out.println("ex:" + ex.getMessage());
throw ex;
}finally {
System.out.println("after");
}
return res;
}
}
测试类
package com.jdkdynamicproxy;
import java.lang.reflect.Proxy;
import com.jdkdynamicproxy.jdkproxy.JdkDynamicProxySubject;
import com.jdkdynamicproxy.service.Subject;
import com.jdkdynamicproxy.service.impl.AgentTarget;
public class JdkDynamicProxyMain {
public static void main(String[] args) {
//配置系统属性sun.misc.ProxyGenerator.saveGeneratedFile为true,代理类生成时会自动将生成的代理类写入硬盘
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Subject subject = (Subject) Proxy.newProxyInstance(
JdkDynamicProxyMain.class.getClassLoader(), //类加载器
new Class[]{Subject.class} , //代理接口
new JdkDynamicProxySubject(new AgentTarget()) //InvocationHandler对象
);
subject.proxyMethod();
}
}
运行如下
程序运行后,在项目目录下生成了代理类的 class 文件
对生成的 $Proxy0.class 文件进行反编译
package com.sun.proxy;
import com.jdkdynamicproxy.service.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m2;
private static Method m3;
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 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 proxyMethod() 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.jdkdynamicproxy.service.Subject").getMethod("proxyMethod");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可以看到生成的 $Proxy0.class 实现了 Subject 接口,重写 proxyMethod 方法。在重写的 proxyMethod 方法中,去调用 JdkDynamicProxySubject 的 invoke(Object proxy, Method method, Object[] args) 方法,实现代理
整个程序的运行流程:Proxy.newProxyInstance(JdkDynamicProxyMain.class.getClassLoader(), new Class[]{Subject.class} , new JdkDynamicProxySubject(new AgentTarget()) ) 创建对象 subject 时,生成了代理类 $Proxy0.class;subject 对象调用proxyMethod 方法时,proxyMethod 方法调用 JdkDynamicProxySubject 的 invoke 方法,invoke 方法中通过反射调用被代理方法,实现动态代理
还没有评论,来说两句吧...