1.JDK动态代理
JDk动态代理是由Java官方提供的动态代理实现方式
依赖于reflect包下的InvocationHandler接口和Method以及Proxy
1.1、JDK动态代理的简单使用
前期准备
1.业务接口
public interface StudentService {
int query();
int save();
}
2.业务实现类
public class StudentServiceImpl implements StudentService {
@Override
public int query() {
System.out.println("开始查询操作");
return 10;
}
@Override
public int save() {
System.out.println("开始保存操作");
return 10;
}
}
3.增强类
public class StudentDao {
public void transaction(){
System.out.println("开始事务");
}
public void closeTransaction(){
System.out.println("关闭事务");
}
}
实现InvocationHandler接口实现方法增强
public class TransactionHandler implements InvocationHandler {
private StudentDao dao;
private StudentServiceImpl student;
public TransactionHandler(StudentDao dao, StudentServiceImpl student) {
this.dao = dao;
this.student = student;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object o;
if("save".equals(method.getName())){
//此处实现save()方法增强
dao.transaction();
o = method.invoke(student, null);
dao.closeTransaction();
} else {
o = method.invoke(student, null);
}
return o;
}
}
测试
public class MyTest {
@Test
public void StudentMain(){
TransactionHandler handler = new TransactionHandler(new StudentDao(), new StudentServiceImpl());
//生成代理对象
StudentService studnetService = (StudentService) Proxy.newProxyInstance(StudentServiceImpl.class.getClassLoader(), StudentServiceImpl.class.getInterfaces(), handler);
//执行save()方法
studnetService.save();
//执行query()方法
studnetService.query();
//该方法用于输出jdk产生的代理类
saveProxyClass("--参数为代理类的输出路径(绝对路径)--");
}
public void saveProxyClass(String path){
byte[] $Proxy1s = ProxyGenerator.generateProxyClass("$Proxy1", StudentServiceImpl.class.getInterfaces());
try(FileOutputStream outputStream = new FileOutputStream(new File(path + "$Proxy1s.class"))) {
outputStream.write($Proxy1s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果
1.2、JDK动态代理底层分析
通过以上测试类的saveProxyClass方法生成如下代理类:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import JDK.service.StudentService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
/*
*本类实例对象是调用Proxy.newProxyInstance()方法后产生
*/
public final class $Proxy1 extends Proxy implements StudentService {
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public $Proxy1(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);
}
}
//代理类产生的save()方法
public final int save() throws {
try {
/*
* h: InvocationHandler实例对象
* m3: 本类静态块加载,m3 = Class.forName("JDK.service.StudentService").getMethod("save");
* Object[]: save()方法参数数组
*/
return (Integer)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
//代理类产生的query()方法
public final int query() throws {
try {
return (Integer)super.h.invoke(this, m4, (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("JDK.service.StudentService").getMethod("save");
m4 = Class.forName("JDK.service.StudentService").getMethod("query");
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());
}
}
}
关键代码
public final int save() throws {
try {
return (Integer)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int query() throws {
try {
return (Integer)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
从以上JDK自动生成的代理类可以看出,这个代理类是通过继承Proxy类和实现被代理类的所有接口生成的,当我们通过代理类调用save()方法的时候,实际是执行了super.h.invoke(this, m3, (Object[])null),查看下图中Proxy类的源码,我们可以发现,h就是InvocationHandler,
而TransactionHandler类实现了InvocationHandler接口,因此调用的便是TransactionHandler中我们实现的invoke()方法。
总结
JDK动态代理通过继承Proxy类和实现被代理类的所有实现接口生成代理类,再通过反射实现方法调用,因此,JDK动态代理只能进行接口代理。
2.Cglib动态代理
2.1、Cglib动态代理的简单使用
前期准备
1.业务接口
public interface StudentService {
int query();
int save();
}
2.业务实现类
public class StudentServiceImpl implements StudentService {
@Override
public int query() {
System.out.println("开始查询操作");
return 10;
}
@Override
public int save() {
System.out.println("开始保存操作");
return 10;
}
}
3.增强类
public class StudentDao {
public void transaction(){
System.out.println("开始事务");
}
public void closeTransaction(){
System.out.println("关闭事务");
}
}
实现MethodInterceptor接口实现方法增强
public class CglibInterceptor implements MethodInterceptor {
private StudentDao dao;
public CglibInterceptor(StudentDao dao) {
this.dao = dao;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object obj;
if("save".equals(method.getName())){
dao.transaction();
obj = methodProxy.invokeSuper(o, objects);
dao.closeTransaction();
} else {
obj = methodProxy.invokeSuper(o, objects);
}
return obj;
}
}
测试
public void StudentMain(){
//输出Cglib产生的代理类
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "--参数为代理类的输出路径(绝对路径)--");
CglibInterceptor interceptor = new CglibInterceptor(new StudentDao());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(StudentServiceImpl.class);
enhancer.setCallback(interceptor);
StudentService student = (StudentService) enhancer.create();
student.save();
student.query();
}
测试结果
2.2、Cglib动态代理的简单使用
Cglib动态代理生成的代理类:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package CGLIB.service.Impl;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a extends StudentServiceImpl implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$save$0$Method;
private static final MethodProxy CGLIB$save$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$query$1$Method;
private static final MethodProxy CGLIB$query$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("CGLIB.service.Impl.StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$2$Method = var10000[0];
CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
CGLIB$toString$3$Method = var10000[1];
CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
CGLIB$hashCode$4$Method = var10000[2];
CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
CGLIB$clone$5$Method = var10000[3];
CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
var10000 = ReflectUtils.findMethods(new String[]{"save", "()I", "query", "()I"}, (var1 = Class.forName("CGLIB.service.Impl.StudentServiceImpl")).getDeclaredMethods());
CGLIB$save$0$Method = var10000[0];
CGLIB$save$0$Proxy = MethodProxy.create(var1, var0, "()I", "save", "CGLIB$save$0");
CGLIB$query$1$Method = var10000[1];
CGLIB$query$1$Proxy = MethodProxy.create(var1, var0, "()I", "query", "CGLIB$query$1");
}
final int CGLIB$save$0() {
return super.save();
}
public final int save() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$save$0$Method, CGLIB$emptyArgs, CGLIB$save$0$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.save();
}
}
final int CGLIB$query$1() {
return super.query();
}
public final int query() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$query$1$Method, CGLIB$emptyArgs, CGLIB$query$1$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.query();
}
}
final boolean CGLIB$equals$2(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$3() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
}
final int CGLIB$hashCode$4() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$5() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1166709344:
if (var10000.equals("query()I")) {
return CGLIB$query$1$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$2$Proxy;
}
break;
case 1872760011:
if (var10000.equals("save()I")) {
return CGLIB$save$0$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$3$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$4$Proxy;
}
}
return null;
}
public StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a var1 = (StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a var10000 = new StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a var10000 = new StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a var10000 = new StudentServiceImpl$$EnhancerByCGLIB$$d8b55a1a;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
关键代码
public final int save() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$save$0$Method, CGLIB$emptyArgs, CGLIB$save$0$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.save();
}
}
通过Cglib生成的代理类可以看出,Cglib生成代理类和JDK生成代理类的区别就是,Cglib并非像JDK一样,通过实现接口生成,Cglib通过继承被代理类实现方法增强,底层实现参考这篇解析CGLIB 动态代理及其原理分析_wadreamer的博客-CSDN博客_cglib动态代理实现原理
总结
JDK通过实现接口进行代理,Cglib通过继承类进行代理,Cglib 在类的生成阶段所做的操作会相对耗时,且生成的类的数目较多,会占据大量的元空间的内存(永久代)。但是,被代理类的子类一旦生成,之后的方法调用则变成搜索方法索引和直接调用,则在 switch-case 块不大,且当前调用方法的 index 在 switch-case 块的前部时,能够获得比 JDK 反射更高的效率。