用途
当现有的类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时候就可以考虑使用代理,通过代理类,扩展原有类的功能,客户端访问的入口只是从目标对象切换到代理对象而已;
jdk代理
JDK 动态代理是基于拦截器和反射实现的,不需要第三方库支持,只需要 JDK 环境即可
- 必须实现 InvocationHandler 接口;
- 使用 Proxy.newProxyInstance 产生代理对象;
- 被代理的对象必须要实现接口;
- 内部采用asm技术动态生成字节码;
public class JdkProxyDemo {
interface Foo{
void show();
}
static class Target implements Foo{
@Override
public void show() {
System.out.println("show");
}
}
static class JdkInvocationHandler implements InvocationHandler{
private Foo foo;
public JdkInvocationHandler(Foo foo){
this.foo=foo;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(foo, args);
//代理类返回的是目标方法执行的结果
System.out.println("after");
return result;
}
}
/**
* jdk代理只能针对接口进行代理
* 内部采用asm技术动态生成字节码()
* @param args
*/
public static void main(String[] args) {
ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();
InvocationHandler handler = new JdkInvocationHandler(new Target());
Foo proxy = (Foo) Proxy.newProxyInstance(classLoader, new Class[]{Foo.class},handler);
proxy.show();
}
}
cglib代理
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要cglib了;
cglib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
/**
* cglib代理是通过父子继承关系创建代理
* 代理对象自身是作为一个子类型的存在
*/
public class CglibProxyDemo {
static class Target {
public void show() {
System.out.println("show");
}
}
public static void main(String[] args) {
Target target = new Target();
Callback callback = new MethodInterceptor() {
// o : 代理类对象自身
//method : 代理类执行的方法
//args : 方法执行参数
//methodProxy : 方法代理【采用这个参数,可以避免使用方法反射进行调用,但是内部未使用反射】
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
/* 基于反射实现
System.out.println("before");
Object result = method.invoke(target, args);
System.out.println("after");
return result;*/
//methodProxy 使用 ,使用目标进行代理
/*System.out.println("before");
Object result = methodProxy.invoke(target,args);
System.out.println("after");
return result;*/
//methodProxy 使用 ,使用自身进行代理
System.out.println("before");
Object result = methodProxy.invokeSuper(o,args);
System.out.println("after");
return result;
}
};
Target proxy = (Target) Enhancer.create(Target.class, callback);
proxy.show();
}
}
参考:https://blog.csdn.net/zhangcongyi420/article/details/125351123