代理模式分为 静态代理 和 动态代理,今天我要讲的是动态代理的两种常见、也是被广泛使用的实现方式-------jdk动态代理 和 Cglib动态代理
第一种:JDK动态代理方式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* JDK动态代理
* 一个类(Proxy)一个接口(InvocationHandler)
* */
public class JDKProxy implements InvocationHandler{
//真实主题对象
private Object target;
/**
* 给主题创建一个代理对象(基于接口实现)
* */
public Object proxy(Object target){
this.target = target;
/*
* 1.类加载器
* 2.接口数组
* 3.InvocationHandler 对象
* */
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
* proxy 代理对象
* method 当前执行的方法
* args 方法的参数数组
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强方法...
System.out.println("前置增强方法");
Object ret = method.invoke(target, args);
//后置增强方法...
System.out.println("后置增强方法");
return ret;
}
优点
- 基于接口实现-----获取真实主题对象的接口,通过反射机制创建一个实现该接口的匿名类,在调用要增强的方法前调用InvacationHandler接口里的invoke方法。因为是jdk自带的功能,所以不需要额外导入第三方jar包
缺点
- 不能对单个类(未实现接口)进行代理,因为jdk动态代理是基于接口实现
第二种:cglib动态代理方式
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* Cglib动态代理 基于:1、继承 2、动态编译
* 1、Enhancer类
* 2、MethodInterceptor 方法拦截器 接口
* */
public class CglibProxy implements MethodInterceptor{
//真实主题对象
private Object target;
/**
* 给主题创建一个代理对象(基于继承实现)
* obj 代理主题
* method 调用方法
* args 参数数组
* mp 代理方法
* */
public Object proxy(Object target){
this.target = target;
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
//前置增强方法...
System.out.println("前置增强方法");
Object ret = mp.invoke(target, args);
//后置增强方法...
System.out.println("后置增强方法");
return ret;
}
}
优点
- 基于类和继承实现----利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。功能十分强大,被代理的类可以不用实现接口,并且运行速度十分快
缺点
- 在java中有一种类是无法被继承的,那就是用final关键字定义的类。而cglib动态代理是基于继承来实现的,所以它唯一的不足就在这里----无法对 final类 进行代理。此外,由于cglib是由第三方组织提供的,所以在使用的时候需要引入cglib的jar包(我这里是用的spring,它里面集成了cglib,若是单独使用cglib,可以直接去mvnrepository.com这个网站下载它的jar包)