# __ .______ __ __ .______ .___________. ______ ______ .___ ___. # | | | _ \ | | | | | _ \ | | / | / __ \ | \/ | # | | | |_) | | |__| | | |_) | `---| |----` | ,----'| | | | | \ / | # | | | ___/ | __ | | ___/ | | | | | | | | | |\/| | # | | | | | | | | | | | | __ | `----.| `--' | | | | | # |__| | _| |__| |__| | _| |__| (__) \______| \______/ |__| |__| # ""$o o$"" ""$o o$" o "$""""o "o $" o""" $" "$o "$o" $o " $ o$" "$o $$$o$$$$o$$$$ $" "oooo o "" ""$$$$$$$$""o"" oo oooo" "$$$$$$oo"oo$$$o" o$$$$oo" o$$$o "o$$$$$$$ "$ $$$$$$$$$oo o$$$$$$$$$o"$" $ $$$ $$$$$$ o$$$$$$ "$$o"o $ $$$$o $$$$$$ $$$$$$$ $$$$o"o $ $$$$$ $$$$$" "$$$$$ $$$$$$ $ $o""""" """" """ """"""$" $ o$$$$$"""$$$$$"$$$$$""$$$$$ooo"o $ o"$o $$$$$$$$oo$$$$$$$$o $$"" $ oo$ "$$$$$$$$$$$$$$$$$$$$" o" o $oo o$$$"$ $$o"o $$$$$$$"" "$$$$$$$ o$$ $$$$o IPHPT BUG o$$$$" $ $$$$ o "$$$$$oo o$$$$$$ "o$$$$ $ $$$$$ o$$"" $ $$$$$o" "$$$$$$$$$$$$$ o o$$$$$o$ "" $$ $$" $ $$$" o"o$$$$$$$$$$$$ " "$$$ $ $$o o$$ "o $$ " $$$$$$$$$$$"o "$$ $ $$$ $$$ oo$ $ o""$$""$$$o " $"o$o $$$o o$$$$ o$$$"o"$oo$$$$o" o $o $$$$$oo$ $$$$o $$$$ $$$$ $$$$" $ $$$$$"" $$ o$$$ """$$$$"o" "$$$o "$$$o $$$" o """ $ $$$oo $$$$o" $$ o$$$"o" """"$ o$$$ o$" $$$ $ "$"" o$"o"$$o$$$$ "$$"o" o$$ "$oo $ " $$o $ "oo$"o$$$"o$o"$$$$o" o" $$$ ""$o $$ $$$o "o$$o$"$$"$$o$$o$$"$$o" $$$ ""o $$$ ""$$$ $$$$$$ $$$$ $" $$$$ $$ $$$$ $$$$"$$$o$ $"" $$$ $$$$ "$$$ """ $$$$ $$"" "$$ oo$" $ooo $ "$$ DesignPattern-Proxy   -  知芯

DesignPattern-Proxy

  • 动机 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。如何在不是去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。

  • 定义 为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。 image.png

  • 总结

  • “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来许多问题,作为间接层的proxy对象便是解决这一问题的常用手段。

  • 具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些对象可能对组件模块提供抽象代理层,在架构层次对对象做proxy。

  • Proxy 并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。

Java 动态代理机制

  • 静态代理模式 以下代码基本符合顶部设计模式类图的内容,静态代理类使得在委托类内部变化的情况下,Client无需关注,同时在代理类可以实现自定义的修改(过滤判断,权限控制等)无需修改委托类。 “`java public interface ISubject { String request(); }

class RealSubject implements ISubject{ @java.lang.Override public String request() { return “hello world!”; } }

```java
class SubStaticProxy implements ISubject{
    private RealSubject reaSubject;

    public SubStaticProxy(RealSubject reaSubject) {
        this.reaSubject = reaSubject;
    }

    @Override
    public String request() {
        return "before request.\n"+reaSubject.request()+"\nAfter request.";
    }
}

但是,如果需要代理多个接口就需要提供对应的代理类,或者修改代理类的代码(一个代理类代理多个接口),如何让代理类在委托类数量增加的情况下固定不变?

  • 动态代理 下面的代码实现了动态代理,Client可以根据需要绑定不同的委托类,系统将会自动根据绑定的委托类动态生成代理类。 “`java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;

public class SubDynamicProxy implements InvocationHandler { private Object realObject;

public Object bind(Object realObject) {
    this.realObject = realObject;
    return Proxy.newProxyInstance(
            realObject.getClass().getClassLoader(),
            realObject.getClass().getInterfaces(),
            this
    );
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("addition process.");
    return method.invoke(realObject, args);
}

}


```java
class Client{
    public static void main(String[] args) {
        // static proxy
        ISubject sub = new SubStaticProxy(new RealSubject());
        System.out.println(sub.request());

        // dynamic proxy
        //加上这句将会产生一个$Proxy0.class文件,这个文件即为动态生成的代理类文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        ISubject dySub = (ISubject) new SubDynamicProxy().bind(new RealSubject());
        System.out.println(dySub.request());
    }
}

代理类是如何生成,又是如何调用 Override 的invoke函数的: 设置属性sun.misc.ProxyGenerator.saveGeneratedFilestrue 可以在运行时看到生成的代理类 $Proxy0.class. 查看newProxyInstance的源码,下面是关键部分:

// 复制接口
final Class<?>[] intfs = interfaces.clone();
// 生成代理类
Class<?> cl = getProxyClass0(loader, intfs);
// 用生成的代理类生成实例并返回
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});

getProxyClass0() 最终调用ProxyGenerator中的generateClassFile() 函数实现class文件的生成: 1. 调用generateMethod()添加equal、toString、hashCode这样的默认方法; 1. 循环获取每个接口内的每个方法,调用generateMethod()添加到代理类。 1. cons.newInstance(new Object[]{h}) 分为两个过程,括号内部就是SubDynamicProxy,也就是newProxyInstance时传入的this;生成类的父类就是ProxyProxy在构造函数设置了h属性为构造传入的参数。 1. generateMethod() 向方法中注入了(String)super.h.invoke(this, method, (Object[])args); 这里的 method 是 m3 = Class.forName("ISubject").getMethod("request"),结合上一步,我们发现都调用到了SubDynamicProxyinvoke方法。在这里做完额外的处理之后再执行委托类的对应方法。最终类之间的依赖关系如下图所示。 image.png


欢迎转载,但请附上本文地址: http://www.codeyourlife.cn/detail/3/

理想和现实,他们是两种人,而我处于两者之间。有时激情昂扬认为自己能改变世界,仔细想来,大多数人注定平凡。