您好,登錄后才能下訂單哦!
這篇文章主要介紹了java代理模式有什么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
我們先來介紹下什么是代理。
代理是一種設計模式,它的核心思想,是將對目標的訪問轉移到代理對象上。這樣做的好處就是,目標對象在不改變代碼的情況下,可以通過代理對象加一些額外的功能。這是一種編程思想,在不改變原有代碼的情況下,通過代理增加一些擴展功能。
代理過程如圖所示,用戶訪問代理對象,代理對象通過訪問目標對象,來達到用戶訪問目標對象的目的,
代理模式包含一下三個角色:
ISubject:接口對象,該接口是對象和它的代理共用的接口。
TargetSubject:目標對象,是實現抽象主題接口的類。
Proxy:代理角色,內部含有對目標對象TargetSubject的引用,從而可以操作真實對象。代理對象提供與目標對象相同的接口,以便在任何時刻都能代替目標對象。同時,代理對象可以在執行目標對象操作時,附加其他的操作,相當于對真實對象進行封裝。
常見的代理模式分為靜態代理和動態代理,動態代理在Java中的實現分為JDK動態代理和cglib代理。
靜態代理
在之前已經說過,在代理模式中有三個角色,一是目標接口,二是目標對象,三是代理對象。
現在以具體代碼來實現,首先是目標接口如下:
public interface IBlogService { void writeBlog(); }
目標對象實現了目標接口,代碼如下:
public class BlogService implements IBlogService { @Override public void writeBlog() { System.out.println("i'm writing..."); } }
靜態代理對象,通過構造方法獲取到目標對象,并實現了目標接口,在目標接口的方法里調用了目標對象的方法,代碼如下:
public class BlogStaticProxy implements IBlogService{ private IBlogService blogService; public BlogStaticProxy(IBlogService blogService) { this.blogService = blogService; } @Override public void writeBlog() { System.out.println("start writing..."); blogService.writeBlog(); System.out.println("end writing..."); } }
靜態代理對象,通過構造方法獲取到目標對象,并實現了目標接口,在目標接口的方法里調用了目標對象的方法,代碼如下:
public class BlogStaticProxy implements IBlogService{ private IBlogService blogService; public BlogStaticProxy(IBlogService blogService) { this.blogService = blogService; } @Override public void writeBlog() { System.out.println("start writing..."); blogService.writeBlog(); System.out.println("end writing..."); } }
測試:
public class TestStaticProxy { public static void main(String[] args) { IBlogService target = new BlogService(); BlogStaticProxy proxy = new BlogStaticProxy(target); proxy.write(); } }
start writing… i’m writing… end writing…
靜態代理,在不修改目標對象的情況下,可以通過代理對象做額外的擴展功能。但靜態方法不是很靈活,如果目標接口的代碼修改,目標對象和代理對象都需要修改。
動態代理在一定程度上避免這種情況,動態代理不需要代理對象實現目標接口,并且上在java 虛擬機的內存中動態的生成代理對象
Jdk動態對象
Jdk的動態代理由Proxy這個類來生成,它有三個參數:
ClassLoader loader,:指定當前目標對象使用類加載器,獲取加載器的方法是固定的
Class<?>[] interfaces,:目標對象實現的接口的類型,使用泛型方式確認類型
InvocationHandler h:事件處理,執行目標對象的方法時,會觸發事件處理器的方法,會把當前執行目標對象的方法作為參數傳入
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { }
Jdk的動態代理代碼如下:
public class JdkBlogProxyFactory { private Object target; public JdkBlogProxyFactory(Object target) { this.target = target; } public Object newInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> { System.out.println("start writing"); Object o = method.invoke(target, args); System.out.println("end writing"); return o; }); } }
測試類:
public class TestJdkProxy { public static void main(String[] args) { IBlogService target = new BlogService(); System.out.println(target.getClass()); // 給目標對象,創建代理對象 IBlogService proxy = (IBlogService) new JdkBlogProxyFactory(target).newInstance(); // class $Proxy0 內存中動態生成的代理對象 System.out.println(proxy.getClass()); // 執行方法 【代理對象】 proxy.writeBlog(); } }
控制臺打印如下:
class com.forezp.proxy.BlogService class com.sun.proxy.$Proxy0 start writing i'm writing... end writing
CGLib動態代理
CGLib采用了非常底層的字節碼技術,其原理是通過字節碼技術為一個類創建子類,并在子類中采用方法攔截的技術攔截所有父類方法的調用,順勢織入橫切邏輯。
CglibBlogFactory代理工廠類如下:
public class CglibBlogFactory implements MethodInterceptor { private Object target; public CglibBlogFactory(Object target) { this.target = target; } //給目標對象創建一個代理對象 public Object getProxyInstance() { //1.工具類 Enhancer en = new Enhancer(); //2.設置父類 en.setSuperclass(target.getClass()); //3.設置回調函數 en.setCallback(this); //4.創建子類(代理對象) return en.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("start writing..."); //執行目標對象的方法 Object returnValue = method.invoke(target, objects); System.out.println("end writing..."); return returnValue; } }
測試類:
public class TestCglib { public static void main(String[] args) { IBlogService target = new BlogService(); //代理對象 IBlogService proxy = (IBlogService) new CglibBlogFactory(target).getProxyInstance(); //執行代理對象的方法 proxy.writeBlog(); } }
運行程序,控制臺打印:
start writing... i'm writing... end writing...
感謝你能夠認真閱讀完這篇文章,希望小編分享的“java代理模式有什么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。