设计模式之代理模式(proxy)

为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

简单来说,就比如说我们不自己建立服务器,而是购买云服务器,而云服务器需要帮我们安装好系统,调试好网络!

代理方式

  • 远程代理:为不同地理的对象,提供局域网代表对象。
  • 虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。
  • 保护代理:控制对一个对象访问的权限。
  • 智能引用代理:提供对目标对象额外的服务。

代理实现

  • 静态代理
  • 动态代理

Java 代理模式(proxy)示例

我们以注册用户需要添加日志

静态代理的实现

public interface UserService {
  public  void add(String name);
}

public class UserServiceImpl implements UserService {
    public void add() {    
        LogHelper.log("注册一个用户 : " + name);
    }
}

// 继承方式
public class LogUserServiceImpl extends UserServiceImpl {
  @Override
  public void add(String name) {    
      super.add(name);
      //写入日志
      LogHelper.log("向日志库添加一条插入用户的日志...");
  }
}

// 聚合方式
public class LogUserServiceImpl2 implements UserService {
  private UserService userService;
  public LogUserServiceImpl2(UserService userService)
  {
    this.userService = userService;
  }
  @Override
  public void add(String name) {    
      userService.add(name);
      //实现开车
      LogHelper.log("向日志库添加一条插入用户的日志...");
  }
}

public class Test{
    public static void main(String[] args) {
        //使用继承方式实现
        UserService u1 = new LogUserServiceImpl();
        u1.add("pangugle");

        //使用聚合方式实现
        UserService u2 = new UserServiceImpl();
        UserService u22 = new LogUserServiceImpl2(u2);
        u22.add("baidu");
    }
}

但是我们会发现,我们每增加一个逻辑,就要写一个类,每次都要修改,能不能动态来改变了? 答案是可以的;

动态代理实现方式

  • JDK动态代理
  • CGLIB动态代理

JDK动态代理和CGLIB动态代理的区别

JDK动态代理:

  • 只能代理实现了接口的类。
  • 没有实现接口的类不能实现JDK的动态代理。

CGLIB动态代理:

  • 针对类来实现代理。
  • 对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。 动态代理的典型应用:spring AOP:同时用到了JDK动态代理和CGLIB动态代理。

JDK动态代理实现日志

public class UserProxy implements InvocationHandler{    
    private Object target;
    public TimeHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        LogHelper.log("添加用户前==========");
        method.invoke(target, args);
        LogHelper.log("添加用户成功==========");
        return null;
    }
}

public class Test
{
  public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    InvocationHandler h = new UserProxy(userService);
    Class<?> cls = userService.getClass();

    UserService userProxy = (UserService) Proxy.newProxyInstance(cls.getClassLoader(),
           cls.getInterfaces(), h);
    userProxy.add("pangugle");
  }
}

运行结果为

【www.pangugle.com】-  添加用户前==========
【www.pangugle.com】-  注册成功 => pangugle
【www.pangugle.com】-  添加用户成功==========