zoukankan      html  css  js  c++  java
  • Java 代理模式

    1、什么是代理

    代理是一种设计模式,它的核心思想,是将对目标的访问转移到代理对象上。这样做的好处就是,目标对象在不改变代码的情况下,可以通过代理对象加一些额外的功能。这是一种编程思想,在不改变原有代码的情况下,通过代理增加一些扩展功能。

    代理过程如图所示,用户访问代理对象,代理对象通过访问目标对象,来达到用户访问目标对象的目的。

     代理模式包含以下三个角色:

      --| ISubject:接口对象,目标对象和代理对象共用的接口

      --| TargetSubject:目标对象,实现共用的接口

      --|    Proxy:代理对象,内部含有对目标对象TargetSubject的引用,从而可以操作真实对象。代理对象提供与目标对象相同的接口,以便在任何时刻都能代替目标对象。同时,代理对象可以在执行目标对象操作时,附加其他的操作,相当于对真实对象进行封装。

    常见的代理模式分为静态代理和动态代理,动态代理在Java中的实现分为JDK动态代理和cglib代理。

    2、静态代理

      1)共用接口对象

    1 package proxy;
    2 
    3 public interface playMovie {
    4     void play();
    5 }

      2)目标对象,实现共用的接口

    1 package proxy;
    2 
    3 public class RealMovie implements playMovie{
    4 
    5     @Override
    6     public void play() {
    7         System.out.println("电影开始播放了");
    8     }
    9 }

      3)代理对象

     1 package proxy;
     2 
     3 public class ProxyMovie implements playMovie{
     4     RealMovie rm;
     5     
     6     public ProxyMovie(RealMovie rm) {
     7         super();
     8         this.rm = rm;
     9     }
    10     
    11     public void guanggao() {
    12         System.out.println("开始放广告了");
    13     }
    14     
    15     @Override
    16     public void play() {
    17         // TODO Auto-generated method stub
    18         guanggao();
    19         rm.play();
    20         System.out.println("电影结束了,散场了");
    21     }
    22 
    23 }

      4)客户端调用

     1 package proxy;
     2 
     3 public class ProxyTest {
     4     public static void main(String[] args) {
     5         RealMovie rm = new RealMovie();
     6         ProxyMovie pm = new ProxyMovie(rm);
     7         pm.play();
     8     }
     9 }
    10 
    11 结果打印:
    12 开始放广告了
    13 电影开始播放了
    14 电影结束了,散场了

    静态代理,在不修改目标对象的情况下,可以通过代理对象做额外的扩展功能。但静态方法不是很灵活,如果目标接口的代码修改,目标对象和代理对象都需要修改。

    动态代理在一定程度上避免这种情况,动态代理不需要代理对象实现目标接口,并且上在java 虚拟机的内存中动态的生成代理对象

    3、动态代理(JDK代理)

    Jdk的动态代理由Proxy这个类来生成,它有三个参数:

    • ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
    • Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
    • InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
    1 public static Object newProxyInstance(ClassLoader loader,
    2                                           Class<?>[] interfaces,
    3                                           InvocationHandler h)
    4         throws IllegalArgumentException
    5     {}

    使用步骤如下:

    1)共用接口对象

    1 package proxy.jdkproxy;
    2 
    3 public interface Subject {
    4     public void doSomething() ;
    5 }

    2)目标对象,实现接口

     1 package proxy.jdkproxy;
     2 
     3 public class RealSubject implements Subject{
     4 
     5     @Override
     6     public void doSomething() {
     7         System.out.println("目标对象:do Something");
     8     }
     9 
    10 }

    3)代理对象

     1 package proxy.jdkproxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class ProxyFactory implements InvocationHandler{
     7     private Object proxied;
     8     
     9     public ProxyFactory(Object proxied) {
    10         this.proxied = proxied;
    11     }
    12 
    13     @Override
    14     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    15         System.out.println("前置增强处理:yoho");
    16         Object obj =method.invoke(proxied, args);
    17         System.out.println("后置增强处理:lalala");
    18         return obj;
    19     }
    20 
    21 }

    4)客户端调用

     1 package proxy.jdkproxy;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 public class ProxyClient {
     6     public static void main(String[] args) {
     7         Subject rs = new RealSubject();
     8         Subject proxyOfrs = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
     9                 new Class[] {Subject.class}, new ProxyFactory(rs));
    10         System.out.println(proxyOfrs);
    11         
    12         proxyOfrs.doSomething();
    13     }
    14 }
  • 相关阅读:
    vue首页组件切换
    vue 页面 添加背景音乐
    vue 新闻列表滚动效果
    vuex中的this.$store.commit
    echarts图例的位置及大小,环图中间字
    octotree — 树形展示 Github 项目代码
    D3 GEO应用专题(一):绘制旋转的3D地球
    vue/cli 3.0脚手架搭建vue项目
    微软锁屏壁纸
    Spring Boot构建RESTful API与单元测试
  • 原文地址:https://www.cnblogs.com/zsy-code/p/13877724.html
Copyright © 2011-2022 走看看