代理的概念

就是为其他对象提供一种代理以控制对这个对象的访问。代理可以在不改动目标对象的基础上,增加其他额外的功能(扩展功能)。通俗的讲就是类似中介/经纪人。

静态代理

概念

静态代理在使用时,需要定义接口或者父类,被代理对象(目标对象)与代理对象(Proxy)一起实现相同的接口或者是继承相同父类。

代码说明

  1. /**
  2. * 主题(动作、行为)
  3. */
  4. public interface Subject {
  5. /**购物*/
  6. public void shopping();
  7. }
  8. /**
  9. * 实现类、决定完成动作的最后一步
  10. */
  11. public class Person implements Subject {
  12. /**
  13. * 完成付款
  14. */
  15. @Override
  16. public void shopping() {
  17. System.out.println("付款了。完成购物");
  18. }
  19. }
  20. public class StaticProxy {
  21. private Subject target;
  22. public StaticProxy(Subject target) {
  23. this.target = target;
  24. }
  25. public void doAction(){
  26. System.out.println("entry proxy");
  27. target.shopping();
  28. System.out.println("out proxy");
  29. }
  30. public static main(String[] args){
  31. Subject subject = new Person();
  32. StaticProxy staticProxy = new StaticProxy(subject);
  33. staticProxy.doAction();
  34. }
  35. }

优点

静态代理可以达到在不改变被代理对象的动作的前提下来扩展新的功能。

缺点

由于代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护,可以使用动态代理方式来解决。

动态代理

概念&特点

  1. 代理对象,不需要实现接口;
  2. 代理对象的生成,是利用JDK的API,动态的在内存中创建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型);
  3. 动态代理也叫做:JDK代理,接口代理;
  4. 底层是通过反射实现的。

代码说明

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * 用于动态生成代理对象
 */
public class CreateProxy implements InvocationHandler {

    private Object target;//被代理的对象,如:Subject

    /**
     * 用于创建代理对象
     * @return
     */
    public Object create(Object target){
       this.target = target;
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
        return proxy;
    }

    /**
     * 代理对象的执行方法
     * @param object 代理对象类
     * @param method 被代理对象的方法
     * @param args 被代理对象的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {

        System.out.println("entry proxy");
        method.invoke(target, args);
        System.out.println("out proxy");
        return null;
    }

    public static main(String[] args){

        Person person = new Person();
        CreateProxy createProxy = new CreateProxy();
        Subject proxy = (Subject) createProxy.create(person);
        proxy.shopping();
    }
}

过程描述

  1. 通过getProxyClass0()生成代理类。JDK生成的最终真正的代理类,它继承自Proxy并实现了我们定义的接口;
  2. 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例;
  3. 调用新实例的方法,即此例中的shopping(),即原InvocationHandler类中的invoke()方法。