JDK动态代理和CGLIB动态代理举例
文章目录
- 前言
- 接口和接口实现类
- JDK 动态代理
- 实现 InvocationHandler 构建代理对象
- 测试方法
- 结果
- CGLIB 动态代理
- 实现 MethodInterceptor 构建代理对象
- 测试方法
- 结果
- 参考文档
前言
代理模式的实现分为静态代理和动态代理,静态代理比较简单,动态代理分为JDK 动态代理和CGLIB动态代理,本文举一个JDK动态代理的小例子。
接口和接口实现类
MyInterface.java
public interface MyInterface {
void printName(String name);
}
MyClass.java
public class MyClass implements MyInterface {
@Override
public void printName(String name) {
System.out.println("Your name is "+name);
}
}
JDK 动态代理
JDK 的基础类库为我们提供了动态代理的实现方案。
需要四个点,3和4可以写到2中,也可以单独写通过构造方法传递到2中:
1、创建接口和接口实现类
2、实现 java.lang.reflect.InvocationHandler 接口,从写 invoke 方法,invoker 方法内部使用反射机制调用目标对象的方法
3、自定义方法 将目标对象委托给代理对象
4、将目标对象传递给 invoke 方法
实现 InvocationHandler 构建代理对象
构建代理对象的过程可以单独存在,不过那样要将目标对象通过构造方法传递到实现类内部,本文参考了 《深入浅出 Mybatis 技术原理与实战》,写在了实现类内部,综合考虑,这样其实使代码简洁了很多。
MyJDKProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/* JDK 动态代理 @author WuJie /
public class MyJDKProxy implements InvocationHandler {//真实的服务对象
private Object target;
/** * 将目标对象委托给代理对象并返回代理对象 * @param target * @return */
public Object bind(Object target){
this.target=target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/** * 当通过代理实例化接口并调用接口方法时,将自动调用 invoke 方法,invoke 方法内部通过反射机制调用目标对象的方法 */
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("自动运行开始");
//反射机制调用方法
method.invoke(target,args);
System.out.println("自动运行结束");
return null;
}
}
测试方法
import org.junit.Test;
/** * JDK动态代理测试 * @author WuJieJecket * */
public class TestMyJDKProxy {
@Test
public void testPrintName(){
MyJDKProxy myProxy=new MyJDKProxy();
MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
myInterface.printName("Jecket");
}
}
结果
自动运行开始
Your name is Jecket
自动运行结束
CGLIB 动态代理
和JDK动态代理相比,接口不是必须的,当然也可以有
实现 MethodInterceptor 构建代理对象
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class MyCglibProxy implements MethodInterceptor {
private Object target;
/** * 创建代理对象 * @param target * @return */
public Object bind(Object target){
//传递目标对象
this.target=target;
//Enhancer:增强者
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("自动调用开始");
//arg1.invoke(target, arg2);
arg3.invoke(target, arg2);
System.out.println("自动调用结束");
return null;
}
}
测试方法
import org.junit.Test;
/** * JDK动态代理测试 * @author WuJieJecket * */
public class TestMyCglibProxy {
//接口模式
@Test
public void testPrintName(){
MyCglibProxy myProxy=new MyCglibProxy();
MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
myInterface.printName("Jecket");
}
//非接口模式
@Test
public void testPrintName2(){
MyCglibProxy myProxy=new MyCglibProxy();
MyClass myClass=(MyClass)myProxy.bind(new MyClass());
myClass.printName("Jecket");
}
}
结果
自动调用开始
Your name is Jecket
自动调用结束
自动调用开始
Your name is Jecket
自动调用结束
参考文档
[1]、https://www.cnblogs.com/luoquan/p/5304296.html
[2]、https://www.cnblogs.com/MOBIN/p/5597215.html
[3]、《深入浅出 Mybatis 技术原理与实战》
还没有评论,来说两句吧...