设计模式23篇之 动态代理详解

动态代理

动态代理:运行时动态的创建代理类(对象),并将方法调用转发到指定类(对象)
动态代理调用的机制图
在这里插入图片描述

  1. ProxyInvocationHandler 组合充当代理的角色.
  2. RealSubject是一个实际对象,它实现接口Subject
  3. 在使用时,我们不希望直接访问 RealSubject 的对象,比如:我们对这个对象的访问是有控制的
  4. 我们使用动态代理,在程序中通过动态代理创建 RealSubject,并完成调用.
  5. 动态代理可以根据需要,创建多种组合
  6. Proxy 也会实现 Subject 接口的方法,因此,使用 Proxy+Invocation 可以完成对 RealSubject 的动态调用。
  7. 但是通过 Proxy 调用 RealSubject 方法是否成功,是由 InvocationHandler 来控制的。(这里其实就是保护代理)
  8. 理解:创建一个代理对象替代被调用的真实对象,使用反射实现控制

JDK动态代理实现示例代码

创建被代理对象的接口类Subject

public interface Subject {
    void request();
}

创建Subject接口的实现类:简单打印一句输出

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("request invoke");
    }
}

创建一个InvocationHandler的实现类

public class ConcreteInvocationHandler implements InvocationHandler {

    private Subject subject;

    public ConcreteInvocationHandler(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        return method.invoke(subject, args);
    }
}
注意: InvocationHandler可以控制安全访问, 作为保护代理

这部分演示语言为Scala, 见谅, 看懂意思就行.

 override def invoke(proxy: scala.Any, method: Method, args: Array[AnyRef]): AnyRef = {

    //如果是get方法就直接调用
    if (method.getName().startsWith("get")) {
      return method.invoke(person)
      //自己不能调用setHotOrNotRating,给自己评分
    } else if (method.getName().equals("setScore")) {
      //返回一个异常,同时invoke throws掉了
      return new IllegalAccessException()
    } 
    null
  }

客户端测试类

public class JDKDynamicProxyTest {
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        InvocationHandler handler = new ConcreteInvocationHandler(subject);
        Subject proxy = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
                RealSubject.class.getInterfaces(), handler);
        proxy.request();
    }
}
发布了125 篇原创文章 · 获赞 236 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_33709508/article/details/103642398