代理模式

代理在我们生活中并不陌生,假如我现在饿了,我可以选择直接去饭店吃,也可以通过外卖平台下单,比如百度外卖、美团外卖、饿了么这些平台本身不生产产品,他们只是商家的搬运工,可以理解成外卖平台就是各种商家的代理。
外卖平台帮我买份饭并送货上门,不仅节约了我去饭店排队的麻烦,可以节约自已很多时间,排队这些细节的问题我不需要关心,目的就是吃上我想吃的饭就ok。我不想自已亲自做的事或着做不到的事(比如中午我需要开个会,没时间去出去),就可以找个代理帮我去做。
现在各大平台都在搞活动,只要下单就可以打折,“打折”算是代理的一个活动,除了给了我想吃的饭还帮我省了部分钱(有的平台送优惠劵)。代理可以帮我完成要做的事情,还可以附加一些代理想做的事情
那我们在开发中什么时候用代理模式呢?
1、自已不想做或着做不到的事
2、需要在现有方法基础上扩展些功能,比如在谋方法执行前后非侵入式打印log

静态代理

public class ProxyDemo {
    public static void main(String args[]){
        RealSubject subject = new RealSubject();
        ProxySubject p = new ProxySubject(subject);
        p.request();
    }
}

interface Subject{
    void request();
}

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

class ProxySubject implements Subject{
    private Subject subject;
    public ProxySubject(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("调用前");
        subject.request();
        System.out.println("调用后"); 
    }
}

其实代理还有一个作用就是隐藏真正实现细节,做为代理类不需要关心执行的方法是怎么实现的。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

上边的实现就是一种静态代理的实现方式,那啥是动态代理呢,说白了Proxy类是通过反射生成的,AOP (面向切面编程)主要是利用动态代理模式的技术来实现的。
动态代理有2种实现方式:
1、使用JDK的Proxy实现的动态代理
2、使用CGlib实现的动态代理

JDK动态代理中包含一个类和一个接口

InvocationHandler接口: 

  public interface InvocationHandler { 
  public Object invoke(Object proxy,Method method,Object[] args) throws   Throwable; 
  } 
  参数说明: 
  Object proxy:指被代理的对象。 
  Method method:要调用的方法 
  Object[] args:方法调用时所需要的参数 

  可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉  ProxySubject。 

Proxy类: 

  Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成    实现类,此类提供了如下的操作方法: 
  public static Object newProxyInstance(ClassLoader loader, Class<?>[]     interfaces, 
  InvocationHandler h) throws IllegalArgumentException 
  参数说明: 
  ClassLoader loader:类加载器 
  Class<?>[] interfaces:得到全部的接口 
  InvocationHandler h:得到InvocationHandler接口的子类实例

实现方式:

public class DynamicProxyDemo01 {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();    //1.创建委托对象
        ProxyHandler handler = new ProxyHandler(realSubject);    //2.创建调用处理器对象
        Subject proxySubject = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
                                                        RealSubject.class.getInterfaces(), handler);    //3.动态生成代理对象
        proxySubject.request();    //4.通过代理对象调用方法
    }
}

/**
 * 接口
 */
interface Subject{
    void request();
}

/**
 * 委托类
 */
class RealSubject implements Subject{
    public void request(){
        System.out.println("====RealSubject Request====");
    }
}
/**
 * 代理类的调用处理器
 */
class ProxyHandler implements InvocationHandler{
    private Subject subject;
    public ProxyHandler(Subject subject){
        this.subject = subject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("调用前");      
        Object result = method.invoke(subject, args);
        System.out.println("调用后");
        return result;
    }
}

使用CGlib实现的动态代理


public class DynamicProxyDemo02 {  
              
            public static void main(String[] args) {  
                RealSubjectCglib cglib=new RealSubjectCglib();  
                RealSubject realSubject=(RealSubject)cglib.getInstance(new RealSubject());  
                realSubject.request();  
            }  
/**
 *没有实现接口的委拖类
 */
class RealSubject {
    public void request(){
        System.out.println("====RealSubject Request====");
    }
}

    public class RealSubjectCglib implements MethodInterceptor {  
            private Object target;  
          
            /** 
             * 创建代理对象 
             *  
             * @param target 
             * @return 
             */  
            public Object getInstance(Object target) {  
                this.target = target;  
                Enhancer enhancer = new Enhancer();  
                enhancer.setSuperclass(this.target.getClass());  
                // 回调方法  
                enhancer.setCallback(this);  
                // 创建代理对象  
                return enhancer.create();  
            }  
          
            @Override  
            // 回调方法  
            public Object intercept(Object obj, Method method, Object[] args,  MethodProxy proxy) throws Throwable {  
                System.out.println("调用前");  
                proxy.invokeSuper(obj, args);  
                System.out.println("调用后");  
                return null;  
            }  
          
        }  
        }  


JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 以前看了很多博客文章,一段时间后,对JDK动态代理还是模模糊糊。这次从思考方式上做一个梳理和推理,彻底搞懂动态代理...
    hanxingruo阅读 4,145评论 0 4
  • 原文连接 简介 Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术。生活中的方方面面都可以...
    zjk_00阅读 2,726评论 0 0
  • 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,...
    SnDragon阅读 5,089评论 2 4
  • 什么是代理模式 代理模式是对象的结构模式。代理模式为其他对象提供一种代理以控制对这个对象的访问。简单来说,在某些情...
    walidake阅读 8,416评论 4 27
  • 生活不止眼前的诗,还有远方你看不到的苟且。 翻朋友圈的的时候无意看到一篇文章:来自X博士的一篇论文截稿,名字叫《带...
    河对岸的窗阅读 3,660评论 0 2