理解jdk和cglib动态代理
jdk动态代理:
jdk动态代理实现前提:必须实现接口。
核心其实是借助【
Proxy.newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)】方法,去创建的动态代理对象
首先简单定义一个fuwu接口, 里面存在四个接口方法。便于理解有无返回值,有无参数。
public interface Fuwu {
/**
* void 类型
*/
void do1();
/**
* int 类型
*/
int do2();
/**
* 有参方法
*/
void do3(int i);
/**
* 有参方法
*/
int do4(int j);
}
其次, 我们需要定义该接口的实现类,也就是我们的目标类(即你真正需要代理的类)。
public class Target implements Fuwu {
@Override
public void do1() {
System.out.println("do1 method 无返回值, 无参数");
}
@Override
public int do2() {
System.out.println("do2 method 有返回值, 无参数");
return 0;
}
@Override
public void do3(int i) {
System.out.println("do3 method 无返回值, 有参数");
}
@Override
public int do4(int j) {
System.out.println("do4 method 有返回值, 有参数");
return j;
}
}
那么代理类是如何运行的?
我们通过反编译可以知道在运行过程中动态生成了代理类Proxy0;为了便于理解,我们先自定义实现Proxy0; 为了便于理解,我们先自定义实现Proxy0;为了便于理解,我们先自定义实现Proxy0;
核心就在于InvocationHandler 接口。InvocationHandler就是代理实例创建时调用的处理程序, 每个实例交由invoke方法来进行代理。
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
一: 自定义代理类$Proxy0(具体见注释):
public class $Proxy0 extends Proxy implements Fuwu {
// 调用父类构造来初始化InvocationHandler
public $Proxy0(InvocationHandler h) {
super(h);
}
// 对应需要代理的方法
static Method do1;
static Method do2;
static Method do3;
static Method do4;
// 通过反射来初始化代理方法, 静态代码块中的异常记得要抛出
static {
try {
do1 = Target.class.getMethod("do1");
do2 = Target.class.getMethod("do2");
do3 = Target.class.getMethod("do3", int.class);
do4 = Target.class.getMethod("do4", int.class);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
@Override
public void do1() {
try {
// 真正代理执行do1方法
h.invoke(this, do1, new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public int do2() {
try {
// 真正代理执行do2方法
return (int) h.invoke(this, do2, new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public void do3(int i) {
try {
// 真正代理执行do3方法
h.invoke(this, do3, new Object[]{i});
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public int do4(int j) {
try {
// 真正代理执行do4方法
return (int) h.invoke(this, do4, new Object[]{j});
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
测试: (输出放在最后)
// 在真正调用时传入InvocationHandler,可以降低代码耦合
Fuwu proxy = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 对应的增强逻辑
System.out.println("before...可增强逻辑");
// 执行代理 并返回
return method.invoke(new Target(), args);
}
});
// 代理执行:
proxy.do1();
System.out.println(proxy.do2());
proxy.do3(10);
System.out.println(proxy.do4(20));
二: 调用核心方法newProxyInstance来创建代理类
这里就不用自定义实现了,因为对应实现其实就是newProxyInstance方法调用逻辑,并且该方法更完善。
实现InvocationHandler接口:
public class MyH implements InvocationHandler {
// 目标代理类
private Fuwu target;
public MyH(Fuwu target) {
this.target = target;
}
// 代理执行 同上
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("增强逻辑 实现InvocationHandler");
return method.invoke(target, args);
}
}
测试:
Fuwu t1 = new Target();
Fuwu newProxyInstance = (Fuwu) Proxy.newProxyInstance(Target.class.getClassLoader(),
Target.class.getInterfaces(), new MyH(t1));
newProxyInstance.do1();
System.out.println(newProxyInstance.do2());
newProxyInstance.do3(10);
System.out.println(newProxyInstance.do4(10));
输出:
增强逻辑 实现InvocationHandler
do1 method 无返回值, 无参数
增强逻辑 实现InvocationHandler
do2 method 有返回值, 无参数
0
增强逻辑 实现InvocationHandler
do3 method 无返回值, 有参数
增强逻辑 实现InvocationHandler
do4 method 有返回值, 有参数
10
-------------------------------------
before...可增强逻辑
do1 method 无返回值, 无参数
before...可增强逻辑
do2 method 有返回值, 无参数
0
before...可增强逻辑
do3 method 无返回值, 有参数
before...可增强逻辑
do4 method 有返回值, 有参数
20
cglib动态代理
cglib动态代理就没有jdk动态代理需要实现接口的局限,它本质是通过继承目标代理类来实现动态代理。
具体实现原理:
其实看上去和jdk动态代理差不多,只不过换了个拦截器一样,需要用到MethodInterceptor。看懂了上面其实这里很好懂。
其中定义了一个intercept接口方法,其中有一个MethodProxy(生成的类将此对象传递给
在调用被拦截的方法时注册MethodInterceptor对象。它可以用于调用原始方法,或对不同的方法调用相同的方法) 感兴趣可以看看源码,用来实现增强式的方法。
public interface MethodInterceptor extends Callback {
Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable;
}
通过继承来实现代理:
public class Proxy extends Targt{
private MethodInterceptor methodInterceptor;
public Proxy() {
}
public Proxy(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
static Method do1;
static Method do2;
static Method do3;
static Method do4;
static {
try {
do1 = Targt.class.getMethod("do1");
do2 = Targt.class.getMethod("do2");
do3 = Targt.class.getMethod("do3", int.class);
do4 = Targt.class.getMethod("do4", int.class);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
@Override
public void do1() {
try {
methodInterceptor.intercept(this, do1, new Object[0], null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public int do2() {
try {
return (int) methodInterceptor.intercept(this, do2, new Object[0], null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public void do3(int i) {
try {
methodInterceptor.intercept(this, do3, new Object[]{i}, null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public int do4(int j) {
try {
return (int) methodInterceptor.intercept(this, do4, new Object[]{j}, null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
测试:
@Test
public void testcglib() {
Proxy proxy = new Proxy();
Targt targt = new Targt();
proxy.setMethodInterceptor(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("增强逻辑...");
return method.invoke(targt, objects);
}
});
proxy.do1();
System.out.println(proxy.do2());
proxy.do3(2);
System.out.println(proxy.do4(2));
}
输出:
增强逻辑...
do1 method 无返回值, 无参数
增强逻辑...
do2 method 有返回值, 无参数
0
增强逻辑...
do3 method 无返回值, 有参数
增强逻辑...
do4 method 有返回值, 有参数
2
本文详细介绍了JDK和CGlib动态代理的实现原理。JDK动态代理基于接口,通过Proxy.newProxyInstance创建代理对象,利用InvocationHandler进行方法拦截;而CGlib动态代理则无需实现接口,通过继承目标类生成子类实现代理,使用MethodInterceptor接口进行方法拦截。文中还给出了具体的代码示例和测试输出,展示了如何在实际操作中应用这两种动态代理技术。

709

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



