代理模式

代理(Proxy):

代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理访问目标对象。这样就可以在目标对象实现的基础上,增强额外的功能操作(扩展目标对象的功能)。可以做到在不修改目标对象的功能前提下,对目标对象功能扩展。

静态代理:

可以在不修改目标对象的前提下扩展目标对象的功能。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。一旦接口增加方法,目标对象与代理对象都要进行修改,代理对象需要与目标对象实现一样的接口。所以静态代理不易维护。静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件。

动态代理:

动态代理不需要实现接口,但是要求对象必须实现接口,否则不能使用动态代理。代理对象生成实例域JDK API,动态的在内存中构建代理对象(需要我们指定创建代理对象、目标对象、实现的接口的类型)。动态代理是运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到jvm中。

java提供了一个Proxy类,调用他的newProxyInstance方法可以生成某个对象的代理对象,该方法需要三个参数:
参数一:ClassLoader loader 生成代理对象使用哪个类装载器(一般使用代理类的装载器)
参数二:Class<>[] interface 生成哪个对象的代理对象,通过接口指定(指定要代理类的接口)
参数三:生成的代理对象的方法里干什么事(实现handler接口)

代理对象用于目标对象相同的方法,因为参数二指定了对象的接口
用户调用代理对象的审美方法,都是在调用处理器的invoke方法
使用JDK动态代理必须要有接口

public class XiaoMing implements Person {
​
    @Override
    public void sing(String name) {
​
        System.out.println("小明唱" + name);
    }
​
    @Override
    public void dance(String name) {
​
        System.out.println("小明跳" + name);
​
    }
}
​
​
public interface Person {
    void sing(String name);
​
    void dance(String name);
}
​
​
public class XiaoMingProxy {
​
    //代理只是一个中介,实际干活的还是小明,于是需要在代理类上维护小明这个变量
    XiaoMing xiaoMing = new XiaoMing();
​
​
    //返回代理对象
    public Person getProxy() {
​
        /**
         * 参数一:代理类的类加载器
         * 参数二:被代理对象的接口
         * 参数三:InvocationHandler实现类
         */
        return (Person)Proxy.newProxyInstance(XiaoMingProxy.class.getClassLoader(), xiaoMing.getClass().getInterfaces(), new InvocationHandler() {
​
            /**
             * proxy : 把代理对象自己传递进来
             * method:把代理对象当前调用的方法传递进来
             * args:把方法参数传递进来
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
​
                //如果别人想要让小明唱歌
                if (method.getName().equals("sing")) {
​
                    System.out.println("给1000万来再唱");
​
                    //实际上唱歌的还是小明
                    method.invoke(xiaoMing, args);
                }
                return null;
            }
        });
​
    }
}

代理与适配器模式的区别:
适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
代理与装饰器模式的区别:
装饰器模式为了增强功能,而代理模式是为了加以控制。

public interface Image {
   void display();
}
​
//真实对象
public class RealImage implements Image {
 
   private String fileName;
 
   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }
 
   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }
 
   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}
​
//代理类
public class ProxyImage implements Image{
 
   private RealImage realImage;
   private String fileName;
 
   public ProxyImage(String fileName){
      this.fileName = fileName;
   }
 
   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}
​
public class ProxyPatternDemo {
   
   public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");
 
      // 图像将从磁盘加载
      image.display(); 
      System.out.println("");
      // 图像不需要从磁盘加载
      image.display();  
   }
}
​
//结果:
Loading test_10mb.jpg
Displaying test_10mb.jpg
​
Displaying test_10mb.jpg
​

cglib代理:

cglib是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象,从而实现对目标对象功能的扩展。

JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用cglib实现。cglib是一个强大的高性能的代码生成包,他可以在运行期扩展java类与实现java接口。广泛的被应用在AOP框架中,为他们提供interception(拦截)。cglib包的底层是通过一个小而块的字节码处理框架ASM,来转换字节码并生成新的类。

cglib与动态代理最大的区别:
使用动态代理的对象必须实现一个或多个接口,使用cglib代理的对象则无需实现接口。
cglib代理无需实现接口,通过生成类字节码实现代理,比反射少块,不存在性能问题,但是cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

代理模式优缺点
优点:
协调调用者和被吊用着,降低了系统的耦合度
代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
缺点:
由于客户端和真实主题之间增加了代理对象,因此会造成请求的处理速度变慢
实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度。
PS:在其他人博客里看到的,代理模式就相当于明星的经济人,海外的代购者哈哈,形象具体生动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值