描述:每一個旅客乘坐火車時,在上車、下車以前須要檢票。站在乘客的角度,這個過程能夠看作一件事:檢票坐車檢票;也能夠看作兩件事:檢票,坐車;站在檢票員的角度,那就是一件事,檢票。java
若是咱們用代碼實現,多是這樣的過程:spring
checkTicket(); takingTrain(); checkTicket();
若是有一天,車站變成刷身份證進站了,咱們就得回去改代碼了... 下面咱們將這個過程分開,用代理來解決坐車意外的問題: 業務邏輯:坐火車 額外須要:檢票/刷卡ide
因此須要一個業務邏輯接口:TakingTrain;函數
package com.spring.mybean; public interface TakingTrain { public void takeTrain(String name); }
實現類:TakingTrainImpl------>要被代理的目標類,實現TakingTrain接口this
package com.spring.mybean.imp; import com.spring.mybean.TakingTrain; public class TakingTrainImpl implements TakingTrain { public void takeTrain(String name) { System.out.println("Hi "+name+ "Welcome to take the train"); } }
加強的橫切邏輯:CheckTicket------>加強類,實現InvocationHandle接口代理
package com.spring.myadvice; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class CheckTicket implements InvocationHandler { private Object target; public CheckTicket(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("please show your tickes"); Object obj=method.invoke(target, args); return obj; } }
調用:code
public class TakingTainingTest { @Test public void takingTrain(){ TakingTrain target=new TakingTrainImpl(); CheckTicket ct=new CheckTicket(target); TakingTrain proxy=(TakingTrain) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), ct); proxy.takeTrain("zhangsan"); } }
打印結果對象
please show your tickes Hi zhangsan Welcome to take the train
好了,咱們知道JDK的動態代理只能對接口進行代理,若是沒有接口怎麼辦呢? CgLib能夠爲一個類建立一個子類,在子類中採用方法攔截的技術攔截父類全部方法的調用,你能夠在這裏加入你的橫切邏輯。 仍是上面的例子,下面咱們用Cglib來實現:繼承
public class CglibProxy implements MethodInterceptor{ private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable { System.out.println("please show your tickes"); return proxy.invokeSuper(arg0, arg2); } }
而後咱們用這個CglibProxy代理類來獲取TakingTrainImpl這個業務的實現類:接口
CglibProxy cglibProxy = new CglibProxy(); TakingTrainImpl takingTrain = (TakingTrainImpl) cglibProxy.getProxy(TakingTrainImpl.class); takingTrain.takeTrain("zhangsan");
上面的方法,咱們直接使用了TakingTrainImpl,沒有在使用它的接口,這就是JDK動態代理和CgLib的區別。