静态代理与动态代理
1、静态代理
说白了就是代理类与目标类都去实现同一个接口,代理类实现方法时,会创建目标类对象。调用目标对象,并在在目标方法前后进行处理。
目标类(Dog):实现工共接口DogInterface,这样一来类Dog就需要实现里面的方法,
代理类(DogProxy):也实现工共接口DogInterface,这样一来类DogProxy就需要实现里面的方法,再方法中调用Dog里面的实现方法并再其方法前后进行处理,便可做到增强的效果。
1.1、工共接口(DogInterface)
public interface DogInterface { void eat(); }
1.2、目标类(Dog)
public class Dog implements DogInterface{ @Override public void eat() { System.out.println("小狗吃骨头!!!"); } }
1.3、代理类(DogProxy)
public class DogProxy implements DogInterface{ // 创建目标对象 private Dog dog; public DogProxy(Dog dog) { this.dog = dog; } @Override public void eat() { // 目标方法前置处理 System.out.println("代理开始。。。。。"); // 调用目标对象的方法 dog.eat(); // 目标方法后置处理 System.out.println("代理结束。。。。。"); } }
1、4、测试类及运行结果
public class StaticTest { public static void main(String[] args) { Dog dog = new Dog(); DogProxy dogProxy = new DogProxy(dog); dogProxy.eat(); } }
代理开始。。。。。
小狗吃骨头!!!
代理结束。。。。。
Process finished with exit code 0
1.5、静态代理的优缺点:
- 优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展。
- 缺点:
- 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。
- 一旦接口增加方法,目标对象与代理对象都要维护。
2、JDK动态代理
动态代理,例如基于接口的代理(JDK代理)。就不在需要去创建代理类,只需要一个代理工厂,可以处理任何类,任何方法的增强处理。
- 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理。
- 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象。
- 动态代理也叫做:JDK代理,接口代理。
- 能在代码运行时动态的改变某个对象的代理,并且能为代理对象动态的增加方法、增加行为。
这里只需要目标类(Dog)实现公共接口,并实现方法即可
2.1、工共接口(DogInterface)
public interface DogInterface { void eat(); void run(); }
2.2、目标类(Dog)
public class Dog implements DogInterface { @Override public void eat() { System.out.println("小狗吃骨头!!!"); } @Override public void run() { System.out.println("小狗跑起来!!!"); } }
2.3、代理工厂(ProxyFactory)
import java.lang.reflect.Proxy; public class ProxyFactory { /** * 维护一个目标对象,Object */ Object target; // 构造器,对目标对象进校初始化 public ProxyFactory(Object target) { this.target = target; } /** * 给目标对象生成一个代理对象 * @return 返回代理对象 */ public Object getProxyInstance() { // 参数说明 // 1. loader /* * public static Object newProxyInstance(ClassLoader loader, * Class<?>[] interfaces, * InvocationHandler h) * ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法固定 * Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方法确定类型 * InvocationHandler h:事情处理,执行目标对象方法时, * 会触发事件处理器方法,会把当前执行的目标对象方法作为一个参数传入 */ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> { System.out.println("JDK代理开始。。。。"); // 通过反射机制调用目标对象的方法 Object invoke = method.invoke(target, args); System.out.println("代理结束。。。。。"); return invoke; }); } }
2.4、测试类及运行结果
public class JdkTest { public static void main(String[] args) { Dog dog = new Dog(); DogInterface dogInterface = (DogInterface)new ProxyFactory(dog).getProxyInstance(); System.out.println("代理类"+dogInterface.getClass()); // 代理方法1 dogInterface.eat(); // 代理方法2 dogInterface.run(); } }
代理类class com.sun.proxy.$Proxy0
JDK代理开始。。。。
小狗吃骨头!!!
代理结束。。。。。
JDK代理开始。。。。
小狗跑起来!!!
代理结束。。。。。
Process finished with exit code 0