动态代理是在运行期间动态地生成代理对象,走出静态代理实现AOP的窘境。
基于Proxy的的动态代理:该机制主要有java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口组成。如下:
//InvocationHandler是我们实现横切逻辑的地方,它是横切逻辑的载体,作用跟
//AOP中的 Advice一样
public class MyInvocationHandler implements InvocationHandler {
private Object target;//目标对象
public MyInvocationHandler 〔Object target〕{
this.target=target;
}
public Object invoke〔Object proxy,Method method,object[]
args〕throws Throwable{
if〔method.getName〔〕.equals〔"reuest"〕〕
//pre-process
Object origrinalObject=method.invoke〔target,args〕;
//post-process
return origrinalObject;
}
}
//使用Proxy和MyInvocationHandler创建不同类型目标对象的动态代理
Subject subject=〔Subject〕Proxy.newProxyInstance〔ProxyRunner.class.getClassLoader〔〕,new Class[]{Subject.class},new MyInvocationHandler〔new SubjectImpl〔〕〕〕;
subject.request〔〕;
//如果为其它目标对象创建代理对象,只需改变上面函数的参数即可。
该代理机制会动态地创建一个$Proxy〔〕类,这个类继承了Proxy并且实现了要代理的目标对象的接口,这也就解释了为什么JDK的动态代理只能代理接口,因为Java是单继承机制。
invoke〔〕方法,第一个参数就是的动态代理对象,第二个参数是目标对象里将要被调用的方法,第三个参数是目标对象里将要被调用的方法的参数。
该代理机制缺陷:只能为实现了接口的类进行代理。
基于CGLIB〔Code Generation Libray〕的动态代理:建立在ASM基础之上,该代理机制可以为接口或类代理,对目标对象进行继承扩展,为其生成相应的子类,而子类可以通过重写来扩展父类的行为,只要将横切逻辑的实现放到子类中,然后让系统使用扩展后的目标对象的子类即可。主要使用net.sf.cglib.proxy.MethodInterceptor接口和net.sf.cglib.proxy.Enhancer类。如下:
// MethodInterceptor是一个回调接口,继承net.sf.cglib.proxy.CallBack回调接口
public MyMethodInterceptor implements MethodInterceptor {
public Ojbect intercept〔Object object, Method method,Object[]
args,MethodProxy proxy〕{
// pre-process
Object o=proxy.invokeSuper〔object,args〕;
//post-process
return o;
}
}
//运行程序
Enhancer enhancer=new Enhancer〔〕;
//假设SubjectImpl没有 实现任何接口
enhancer.setSuperclass〔SubjectImpl.class〕;
enhancer.setCallBack〔new MyMethodInterceptoer〔〕〕;
SubjectImplProxy proxy=〔SubjectImpl〕enhancer.create〔〕;
proxy.request〔〕;
intercept〔〕方法中的参数依次为代理对象、被调用方法的Method对象、方法参数、CGLIB提供的方法代理对象,一般来说调用目标方法时,使用最后一个参数,而不直接使用JAVA反射,因为CGLIB使用ASM的字节码操作,代理对iangde执行效率比反射机制高。
该机制缺陷:使用CGLIB对类进行扩展的唯一限制就是无法对final方法进行重写。