一、什么是 动态代理
动态代理模式是对方法的横向增强,它不同于继承,继承通过对父类方法的覆盖,重新对方法进行定义,而横向增强是对方法执行前和执行后的一个增加,不重新定义方法。简单来说,就是可以在不修改源码的前提下,可以对某个方法增加功能。
代理方式有两种:
1.JDK动态代理:对接口或实现接口的类进行代理
2.CGLib动态代理:对类进行代理
本文主要介绍的是JDK动态代理
二、JDK动态代理演示
jdk动态代理机制中必不可少的类和接口,一个是InvocationHandler(接口)、另一个是Proxy(类)。
必须有一个类实现InvocationHandler接口,从而实现其中的invoke()方法,在invoke()方法中对代理的方法进行增强。
创建被代理接口及实现类:
public interface Animal {
public void eat();
}
public class Person implements Animal {
@Override
public void eat() {
System.out.println("人是动物,所以需要吃东西");
}
}
创建代理类:
//创建代理类
public class MyProxy {
//获取代理对象,返回增强之后的方法
public static Object getProxy(Animal animal) {
//获取jdk的动态代理生成代理对象
Object proxy= Proxy.newProxyInstance(MyProxy.class.getClassLoader(),
animal.getClass().getInterfaces()
, new InvocationHandler() {
@Override
//重写invoke方法,当调取getProxy,invoke就会执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("在吃定西之前,还需要烹饪,讲究色香味俱全");
//对目标对象的方法进行增强,这是切入点
Object result=method.invoke(animal,args);
System.out.println("吃完饭之后还要收拾桌子,洗碗");
return result;
}
});
return proxy;
}
结果测试:
public class Main {
public static void main(String[] args) {
//创建被代理类对象
Animal person=new Person();
将被代理对象作参数传入
Object proxyobj=MyProxy.getProxy(person);
Animal proxy=(Animal) proxyobj;
proxy.eat();
}
}
运行结果:
在吃定西之前,还需要烹饪,讲究色香味俱全
人是动物,所以需要吃东西
吃完饭之后还要收拾桌子,洗碗
Process finished with exit code 0
从以上实例中,可以看到在没有修改eat方法源码的情况下,使用jdk代理,之后,再调用eat(),是我们增强之后的方法。
注意;jdk代理必须要有接口,JDK动态代理必须要有接口,对接口中的方法进行增强,而实现类中有他特有的方法,代理类无法对他进行增强,通过Proxy对象只能得到接口对象,不能得到实现类对象,所以强转的时候,只能是接口的对象。