一、JDK动态代理
通过使用Proxy和InvocationHandler 来动态创建对象的方式。
Proxy:提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
一般我们通过JDK动态代理是通过下面这个方法。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
这里简单解释一下参数的意思:
ClassLoader loader : 类加载器
Class<?>[] interfaces : 目标对象实现的接口类型
InvocationHandler h : 执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入。
举个栗子:
public class JDKProxy implements InvocationHandler {
/**
* Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。
* 如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:
* 如果需要为一个或多个接口动态地创建实例,也可以使用Proxy来创建动态代理实例。
* Proxy提供了如下两个方法来创建动态代理类和动态代理实例:
*/
/**
* 要代理的对象
*/
private Object subject;
public JDKProxy(Object subject) {
this.subject = subject;
}
/**
* 重写invoke 方法
* @param proxy 代理对象
* @param method 需要增强的方法
* @param args 方法需要的参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK 动态代理:查询之前的校验逻辑......");
Object invoke = method.invoke(subject, args);
System.out.println("JDK 动态代理:查询之后的校验逻辑......");
return invoke;
}
public static void main(String[] args) {
P person = new Person();
P p = (P)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new JDKProxy(person));
p.query();
/**
* 总结一下,一共分为以下四步
* 1、通过实现 InvocationHandler 接口创建自己的调用处理器;
* 2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
* 3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
* 4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
*/
}
}
interface P{
public void query();
}
class Person implements P{
public void query(){
System.out.println("我在找东西。。。。。。");
}
}
输出结果是:
这些就能动态在执行方法前后做一些自己的业务逻辑。
二、CGLIB动态代理
Cglib代理也叫做子类代理,是通过继承的方式对目标对象进行功能扩展
public class MyMethodInterceptor implements MethodInterceptor {
/**
* CGLIB 增强类对象,代理类对象是由 Enhancer 类创建的,
* Enhancer 是 CGLIB 的字节码增强器,可以很方便的对类进行拓展
*/
private Enhancer enhancer = new Enhancer();
/**
*
* @param o 被代理的对象
* @param method 代理的方法
* @param args 参数
* @param methodProxy CGLIB产生的代理对象
* @return cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLIB 被代理之前");
methodProxy.invokeSuper(o,args);
System.out.println("CGLIB 被代理之后");
return null;
}
public Object newProxyInstance(Class<?> c){
/**
* 设置产生的代理对象的父类,增强类型
*/
enhancer.setSuperclass(c);
/**
* 定义代理逻辑对象为当前对象,要求当前对象实现 MethodInterceptor 接口
*/
enhancer.setCallback(this);
/**
* 使用默认无参数的构造函数创建目标对象,这是一个前提,被代理的类要提供无参构造方法
*/
return enhancer.create();
}
}
class TestCglib{
public static void main(String[] args) {
MyMethodInterceptor cglib = new MyMethodInterceptor();
Animal o = (Animal)cglib.newProxyInstance(Animal.class);
o.query();
}
}
class Animal{
public void query(){
System.out.println("大象在喝水......");
}
}
执行结果如图所示
因为Cglib是通过继承的方式创建动态代理,所以说被代理的对象不能是被final修改时类,否则会报java.lang.IllegalArgumentException:
目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.