一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java動態代理(jdk與cglib)詳細解析

java動態代理(jdk與cglib)詳細解析

2019-10-14 13:53java之家 Java教程

靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了

JAVA的動態代理 

代理模式 
代理模式是常用的java設計模式,他的特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后處理消息等。代理類與委托類之間通常會存在關聯關系,一個代理類的對象與一個委托類的對象關聯,代理類的對象本身并不真正實現服務,而是通過調用委托類的對象的相關方法,來提供特定的服務。 
按照代理的創建時期,代理類可以分為兩種。

靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。

動態代理:在程序運行時,運用反射機制動態創建而成。 

首先看一下靜態代理: 
1、Count.java 

復制代碼代碼如下:

package net.battier.dao;  

/** 
 * 定義一個賬戶接口 
 *  
 * @author Administrator 
 *  
 */  
public interface Count {  
    // 查看賬戶方法  
    public void queryCount();  

    // 修改賬戶方法  
    public void updateCount();  

}  


2、CountImpl.java 

復制代碼代碼如下:

package net.battier.dao.impl;  

import net.battier.dao.Count;  

/** 
 * 委托類(包含業務邏輯) 
 *  
 * @author Administrator 
 *  
 */  
public class CountImpl implements Count {  

    @Override  
    public void queryCount() {  
        System.out.println("查看賬戶方法...");  

    }  

    @Override  
    public void updateCount() {  
        System.out.println("修改賬戶方法...");  

    }  

}  

CountProxy.java  
package net.battier.dao.impl;  

import net.battier.dao.Count;  

/** 
 * 這是一個代理類(增強CountImpl實現類) 
 *  
 * @author Administrator 
 *  
 */  
public class CountProxy implements Count {  
    private CountImpl countImpl;  

    /** 
     * 覆蓋默認構造器 
     *  
     * @param countImpl 
     */  
    public CountProxy(CountImpl countImpl) {  
        this.countImpl = countImpl;  
    }  

    @Override  
    public void queryCount() {  
        System.out.println("事務處理之前");  
        // 調用委托類的方法;  
        countImpl.queryCount();  
        System.out.println("事務處理之后");  
    }  

    @Override  
    public void updateCount() {  
        System.out.println("事務處理之前");  
        // 調用委托類的方法;  
        countImpl.updateCount();  
        System.out.println("事務處理之后");  

    }  

}  


3、TestCount.java 

復制代碼代碼如下:

package net.battier.test;  

import net.battier.dao.impl.CountImpl;  
import net.battier.dao.impl.CountProxy;  

/** 
 *測試Count類 
 *  
 * @author Administrator 
 *  
 */  
public class TestCount {  
    public static void main(String[] args) {  
        CountImpl countImpl = new CountImpl();  
        CountProxy countProxy = new CountProxy(countImpl);  
        countProxy.updateCount();  
        countProxy.queryCount();  

    }  
}  


觀察代碼可以發現每一個代理類只能為一個接口服務,這樣一來程序開發中必然會產生過多的代理,而且,所有的代理操作除了調用的方法不一樣之外,其他的操作都一樣,則此時肯定是重復代碼。解決這一問題最好的做法是可以通過一個代理類完成全部的代理功能,那么此時就必須使用動態代理完成。 

再來看一下動態代理: 
JDK動態代理中包含一個類和一個接口: 
InvocationHandler接口: 
public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

參數說明: 
Object proxy:指被代理的對象。 
Method method:要調用的方法 
Object[] args:方法調用時所需要的參數

 

可以將InvocationHandler接口的子類想象成一個代理的最終操作類,替換掉ProxySubject。

Proxy類: 
Proxy類是專門完成代理的操作類,可以通過此類為一個或多個接口動態地生成實現類,此類提供了如下的操作方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler h) 
                               throws IllegalArgumentException 
參數說明: 
ClassLoader loader:類加載器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子類實例

Ps:類加載器 
在Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器; 
Booststrap ClassLoader:此加載器采用C++編寫,一般開發中是看不到的; 
Extendsion ClassLoader:用來進行擴展類的加載,一般對應的是jre\lib\ext目錄中的類; 
AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。

動態代理 
與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟件系統的可擴展性,因為Java 反射機制可以生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。

動態代理示例: 
1、BookFacade.java 

復制代碼代碼如下:

package net.battier.dao;  

public interface BookFacade {  
    public void addBook();  
}


2、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;  
    }  

}  


3、TestProxy.java 

復制代碼代碼如下:

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修飾的類進行代理。

示例 
1、BookFacadeCglib.java 

復制代碼代碼如下:

package net.battier.dao;  

public interface BookFacade {  
    public void addBook();  
}  


2、BookCadeImpl1.java 

復制代碼代碼如下:

package net.battier.dao.impl;  

/** 
 * 這個是沒有實現接口的實現類 
 *  
 * @author student 
 *  
 */  
public class BookFacadeImpl1 {  
    public void addBook() {  
        System.out.println("增加圖書的普通方法...");  
    }  
}  


3、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;  

  
    }  

}  


4、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();  
    }  
}  

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲高清中文字幕一区二区三区 | 亚洲 欧美 制服 校园 动漫 | 国产色综合久久五月色婷婷中文 | 深夜在线观看 | 色噜噜 男人的天堂在线观看 | 毛片在线播放a | 国产精品一区二区三区免费 | 精品一区二区三区 不卡高清 | 青柠网在线观看视频 | 欧美性xxxxx| 无码中文字幕av免费放 | 国产精品99久久 | 视频在线播放 | kk4444了欧美 | 天码毛片一区二区三区入口 | 亚洲成色WWW久久网站夜月 | 香蕉久久夜色精品国产尤物 | 国产高清亚洲 | 毛片在线免费观看网站 | 动漫美女胸被狂揉扒开吃奶动态图 | 国产在线观看一区 | 久久re热在线视频精69 | 成人精品一区二区三区中文字幕 | 女仆掀起蕾丝裙被打屁股作文 | 91午夜在线观看 | 国产欧美日韩精品在线 | 日韩在线一区二区 | 成人免费高清视频 | www.九九| 精品国产午夜久久久久九九 | 极品丝袜老师h系列全文阅读 | 欧美一级专区免费大片俄罗斯 | 欧美xxoo黑人又粗暴 | 2012手机在线中文字幕 | 亚洲高清在线天堂精品 | 精品亚洲综合在线第一区 | 亚洲高清毛片一区二区 | 久久久久综合 | 欧美成人手机 | 国产男女乱淫真视频全程播放 | 精品视频99|