JDK動態代理中包含一個類和一個接口:
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
參數說明:
Object proxy:指被代理的對象。
Method method:要調用的方法
Object[] args:方法調用時所須要的參數 java
能夠將InvocationHandler接口的子類想象成一個代理的最終操做類,替換掉ProxySubject。 ide
Proxy類:
Proxy類是專門完成代理的操做類,能夠經過此類爲一個或多個接口動態地生成實現類,此類提供了以下的操做方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
參數說明:
ClassLoader loader:類加載器
Class<?>[] interfaces:獲得所有的接口
InvocationHandler h:獲得InvocationHandler接口的子類實例 this
1.什麼是動態代理?
一種用於轉發請求,進行特殊處理的機制,「動態」應該指的是「運行期」。
2.爲何使用動態代理?
能夠對請求進行任何處理(如事務,日誌等,這都是網上說的,我固然能夠作任何處理)
3.使用它有哪些好處?
如上
4.哪些地方須要動態代理?
不容許直接訪問某些類;對訪問要作特殊處理等spa
動態代理示例:
一、BookFacade.java 代理
package net.battier.dao; public interface BookFacade { public void addBook(); }
二、BookFacadeImpl.java 日誌
package net.battier.dao.impl; import net.battier.dao.BookFacade; public class BookFacadeImpl implements BookFacade { @Override public void addBook() { System.out.println("增長圖書方法。。。"); } } 、BookFacadeProxy.java package net.battier.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK動態代理代理類 * * @author student * */ public class BookFacadeProxy implements InvocationHandler { private Object target; /** * 綁定委託對象並返回一個代理類 * @param target * @return */ public Object bind(Object target) { this.target = target; //取得代理對象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); //要綁定接口(這是一個缺陷,cglib彌補了這一缺陷) } @Override /** * 調用方法 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; System.out.println("事物開始"); //執行方法 result=method.invoke(target, args); System.out.println("事物結束"); return result; } }
三、TestProxy.java code
package net.battier.test; import net.battier.dao.BookFacade; import net.battier.dao.impl.BookFacadeImpl; import net.battier.proxy.BookFacadeProxy; public class TestProxy { public static void main(String[] args) { BookFacadeProxy proxy = new BookFacadeProxy(); BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl()); bookProxy.addBook(); } }
可是,JDK的動態代理依靠接口實現,若是有些類並無實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。 對象
Cglib動態代理
JDK的動態代理機制只能代理實現了接口的類,而不能實現接口的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。
示例
一、BookFacadeCglib.java blog
package net.battier.dao; public interface BookFacade { public void addBook(); }
二、BookCadeImpl1.java 繼承
package net.battier.dao.impl; /** * 這個是沒有實現接口的實現類 * * @author student * */ public class BookFacadeImpl1 { public void addBook() { System.out.println("增長圖書的普通方法..."); } }
三、BookFacadeProxy.java
package net.battier.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib動態代理 * * @author student * */ public class BookFacadeCglib implements MethodInterceptor { private Object target; /** * 建立代理對象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回調方法 enhancer.setCallback(this); // 建立代理對象 return enhancer.create(); } @Override // 回調方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物開始"); proxy.invokeSuper(obj, args); System.out.println("事物結束"); return null; } }
四、TestCglib.java
package net.battier.test; import net.battier.dao.impl.BookFacadeImpl1; import net.battier.proxy.BookFacadeCglib; public class TestCglib { public static void main(String[] args) { BookFacadeCglib cglib=new BookFacadeCglib(); BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); bookCglib.addBook(); } }