静态代理:了解设计模式中的代理模式的童鞋应该都知道,如果想要生成代理类,需要让代理类和被代理类实现同一个接口,并且在代理类中添加被代理类的引用,代理类方法实现中添加代理逻辑,并决定是否调用被代理类方法,这种通过硬编码的方式指定代理类与被代理类的方式,叫静态代理。可以明显看出,静态代理类与被代理类是强耦合的,如果要代理100个类,你就得写100个代理类
动态代理:其实动态代理与静态代理的本质一样,最终程序运行时都需要生成一个代理对象实例,通过它来完成相关增强以及业务逻辑,只不过静态代理需要硬编码的方式指定,而动态代理则是以动态方式生成代理(有编译时操作字节码生成的方式、运行时通过反射、字节码生成的方式)。动态生成的好处很明显,代理逻辑与业务逻辑是互相独立的,没有耦合,代理1个类或100个类要做的事情没有任何区别
说到耦合,必须把AOP拿来说道说道:传统面向对象思想中,如果想要实现功能复用,要么继承、要么引用,无论哪种方式,对代码都有一定的侵入性,耦合无可避免,侵入性啥意思?简单来说:如果你想要用它增强你程序的功能,你必须改动你的程序代码,那它就具有侵入性。如果只有一点两点需要增强还好说,如果大量的功能点需要被增强,工作量就会很大,代码也不太优雅。想象一下,如果你对外公开了一系列的接口,现在领导说了,接口要加权限控制。在哪加?最笨的当然就是写个程序验证的逻辑,然后每个接口都拿来调用一遍。这也正是面向对象思想的短板,在要为程序新增一些通用功能时,只能通过耦合的方式才能进行。AOP正是为此而生,AOP旨在通过一种无耦合的方式来为程序带来增强。而动态代理,就是AOP实现方式中的一种
我举两个例子,说明下用动态代理实现功能增强,要怎么做,怎么就解耦了,哪里就方便了:
springAOP大家一定耳熟能详,它借鉴了AOP的思想,通过动态代理实现功能的无耦合增强,企业级应用开发时,当需要为程序添加通用功能时,springAOP应该是你的首选之一,比如现在要给系统对外的一系列接口添加一个权限验证功能,只需要两步即可
编写切面类,如下:
@Aspect @Component public class AuthAspect{ @Around(value="pointCut()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ if(!havePermission()) return "没有权限..."; return pjp.proceed(pjp.getArgs()); } }
可以看到,代理逻辑是独立的,没有也不需要任何与被代理相关的内容,是为解耦,有了代理逻辑后,我们只要按照spring的规则配置好要代理的范围就好了(也就是代理哪些类的哪些方法),spring会为这些目标类生成动态代理对象,功能增强就是如此简单
RPC框架大家应该也都接触过,客户端可以像调用本地对象的方法一样调用远程方法,这里的本地对象其实就是个动态代理对象,在rpc中,这类代理对象有个专业的名字,叫做stub(桩),stub对象的创建方式大概是这样的:
为了方便理解,我将其简化了下,这里使用了jdk自带的代理对象生成方法,Proxy.newProxyInstance,需要在InvocationHandler的invoke方法中实现代理逻辑,在rpc框架中,代理逻辑可以简单理解为连接服务提供端,发送请求,获取返回。有了这个createStub方法,就可以很方便的生成任意我们想要调用的服务的代理对象了,还是非常方便的;这就是解耦的好处..
总结一下:代理分为静态代理和动态代理,静态代理将代理类和被代理类耦合在一起,实现增强时非常不便,需要大量编码;
AOP的宗旨是实现无耦合的增强,动态代理就是AOP思想的实现方式之一,无耦合的方式对代码没有侵入性,可以很方便的实现功能增强,如果你需要给你的代码添加一些通用的增强功能,你应该第一时间想到动态代理
PS:如果有不足之处,欢迎指出;如果解决了你的疑惑,就点个赞吧o(* ̄︶ ̄*)o