puterprogramming,theproxypatternisasoftwaredesignpattern.Aproxy,initsmostgeneralform,isaclassfunctioningasaninterfacetosomethingelse.Theproxycouldinterfacetoanything:workconnection,alargeobjectinmemory,afile,orsomeotherresourcethatisexpensiveorimpossibletoduplicate.(所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、存储器中的大对象、文件或其它昂贵或无法复制的资源。)——引用自维基百科
维基百科所说的优点抽象,这里我们简单来讲就是通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。
某买家去看房,觉得采光和低端都不错,决定买下这个房子。这个时候买家就找到中介公司,也就是我们的代理者,帮我们的买家处理售前售后工作,并安排好一切交付事项。这里的一切都围绕房子所展开,于是我们可以把房源(或者房地产商)当做是我们的接口,然后我们的中介机构代理相关事项,买家谈妥后并不需要和房地产商有什么直接的交涉便可一步到位。
这里我们根据房源,分别让顾客和中介实现相关接口方法,把买家交给中介结构处理相关事项,然后调用相关方法即可。
动态代理需要实现InvocationHandler接口,相比静态代理而言有一个好处就是:不需要生成代理类,可扩展性强,方便后续的更改和操作。
CGLIB代理的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言例如Groovy和BeanShell,也是使用ASM来生成java的字节码。当然不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
输出结果和上面的效果一样,这里不做重复展示,值得一提的CGLIB代理是使用Enhancer来处理相关的类和接口的实现的,这个地方是其独有的特点。
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。①如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP②如果目标对象实现了接口,可以强制使用CGLIB实现AOP③如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换