jdk動態代理與cglib動態代理

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();  
    }  
}  
相關文章
相關標籤/搜索