aop最重要的实现还是代理,说到代理,就有两种了,一种是jdk的,一种是基于cglib。二者还是有很多区别的,spring底层就是基于cglib。
Jdk
Jdk代理呢,有个特点就是必须基于接口代理,什么意思呢,就是代理的对象必须实现一个接口。今儿代理对象也将会实现该接口。然后通过反射来调用方法进而达到增强方法的目的。光说可能听不太懂,接下来实操一下。
我们现在来说说以下代码的意思,Target是代理的目标对象,实现了Foo接口,重写了foo方法。在main方法中,我们通过Proxy.newProxyInstance()创建代理对象。可以看到此时需要三个参数,我们一一说明,第一个参数,是类加载器,为什么需要类加载器呢,我们知道代理类是动态生成的字节码,他并没有源码,所以需要直接给一个类加载器为其进行加载。第二个就是目标类实现的接口类,可以看到可以实现多个接口,最后一个就是当我们调用返回的代理对象中的方法是会执行的回调方法。 因为之前说过jdk的动态代理是和目标对象实现同一个接口,所以返回动态代理对象时直接强转为接口类型即可。
我们现在来着重说下这个回调函数,可以看到也是三个参数,第一个参数是代理对象,第二个是正在执行的方法对象,第三个是方法参数。 我们就可以在该回调函数中对目标方法进行增强。 我们通过反射来执行的方法,我们是先在外new了一个目标对象实例,作为方法的执行对象。 return返回的就是方法的返回值。
看最终结果,目标方法确实被加强了
根据以上的实验,我们需要注意几个点。
1.代理对象和目标对象并不是继承关系,他们都是实现了同一个接口,也不能相互类型转换。
2.既然目标对象和代理对象不是继承关系,那么目标对象可不可以是final的,答案是可以的,既然无继承关系,所以是不是final的也无所谓。
Cglib
Cglib就不需要目标对象实现接口了,Cglib是通过继承目标对象,重写目标方法,进而达到方法的增强。下面就来演示下,其实和jdk的代码实现差不多。
可以看到,Cglib的代理对象是通过Enhancer的create方法创建,此时只需要两个参数,第一个参数就是目标对象,第二个也就是相当于回调函数,当代理对象执行方法时,会执行该方法。
可以看到操作方法还是差不多。最终方法也成功被增强
我们同样需要注意几个点
1.通过Cglib实现的动态代理对象,是和目标对象是继承关系,所以可以进行类型转化。
2.既然是继承关系,那么目标对象就不能再用final修饰,否则代理对象不能生成,同时方法也不能带有final,因为Cglib本质就是通过方法的重写来对方法进行增强的。




