AOP是指面向切面編程。編程
在學習AOP以前先來了解一下代理,由於傳說中的AOP其實也對代理的一種應用。框架
首先來看這樣一段代碼:maven
public interface Hello { void say(String name); }
實現類:學習
public class HelloImpl implements Hello { public void say(String name) { System.out.println("Hello!"+name); } }
若是如今須要在say調用的先後作一些操做,那最簡單的方法就是直接在say方面中增長代碼,但這樣確定不夠優雅。this
這時候能夠用第一種代理模式:靜態代理spa
public class HelloProxy implements Hello { private Hello hello; public HelloProxy(){ hello=new HelloImpl(); } public void say(String name) { before(); hello.say(name); after(); } private void before(){ System.out.println("before"); } private void after(){ System.out.println("after"); } }
這樣咱們在保留原來HelloImple中say方法的同時,用HelloProxy代理在say方法的先後增長了before和after代理
調用一下試試:code
public static void main(String[] args){ Hello helloProxy=new HelloProxy(); helloProxy.say("Gary"); }
運行結果:對象
那麼新的問題來了,若是每次都須要寫一個代理類不也很麻煩嗎,項目中就會有不少個xxxProxy,所以就出現了 JDK動態代理。blog
代碼以下:
public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target){ this.target=target; } public <T> T getProxy(){ return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result=method.invoke(target,args); after(); return result; } private void before(){ System.out.println("before"); } private void after(){ System.out.println("after"); } }
注:Proxy.newProxyInstance()參數有三個:
在該類中target就是被代理的對象,該類實現了InvocationHandler接口,經過反射去動態建立Hello接口的代理類
那麼如今的調用就變簡單了:
public static void main(String[] args){ DynamicProxy dynamicProxy=new DynamicProxy(new HelloImpl()); Hello helloProxy= dynamicProxy.getProxy(); helloProxy.say("gary"); }
用了JDK動態代理後,咱們以爲仍是有問題,若是要代理一個沒有接口的類,該怎麼辦呢,因而就輪到咱們的 CGlib動態代理 出場了。
在Spring、Hibernate等框架中都用到了CGlib動態代理,maven資源以下:
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.6</version> </dependency>
他的使用須要實現MethodInterceptor類,並完成intercept方法。CGlib 提供的是方法級別的代理:
public class CGLibProxy implements MethodInterceptor { public <T> T getProxy(Class<T> cls){ return (T) Enhancer.create(cls,this); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { before(); Object result=methodProxy.invokeSuper(o,objects); after(); return result; } private void before(){ System.out.println("before"); } private void after(){ System.out.println("after"); } }
這樣使用時就不須要提供接口了:
public static void main(String[] args){ CGLibProxy cgLibProxy= new CGLibProxy(); Hello hello=cgLibProxy.getProxy(HelloImpl.class); hello.say("Gary"); }
最後再改造一下,加上單例模式就更完美了
private static CGLibProxy instance=new CGLibProxy(); private CGLibProxy(){ }
public static CGLibProxy getInstance(){ return instance; }
調用就改成:
public static void main(String[] args){ Hello hello=CGLibProxy.getInstance().getProxy(HelloImpl.class); hello.say("Gary"); }