jdk动态代理源码分析(一)---代理的定义
生活随笔
收集整理的這篇文章主要介紹了
jdk动态代理源码分析(一)---代理的定义
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在看rpc的實現原理,發現大部分通用的rpc框架在實現遠程調用的時候,都是通過java動態代理封裝好了通信細節,讓用戶可以像調用本地服務一樣調用遠程服務。但是關于java動態代理有兩個問題想不通:jdk動態代理中的invoke方法是如何被自動調用的?jdk動態代理為什么只針對實現了接口的類?帶著這兩個問題,我仔細讀了下源碼。 代理的基本定義 代理模式定義:給某個原對象提供一個接口實現類(代理類),客戶端不直接訪問這個對象,而是通過代理類來間接訪問。 代理模式涉及到了四個對象: Client:服務調用方,通過代理類調用真實服務(serviceImpl)。 IService:功能接口類,類中包含了功能點的抽象。是serviceImpl 和 Proxy都要去實現的接口。 ServiceImpl:功能接口的具體實現類。 Proxy:代理類。其中包含了對功能時間類(ServiceImpl)的引用,從而可以操作真實服務接口。并且可以在調用真實服務處的前后進行一系列其他操作。 對象之間關系為:
?
代理的分類與使用 java代理主要分為靜態代理和動態代理兩類。 1、靜態代理:所謂靜態是指,在程序運行前已經寫好并編譯成了.class文件,而不是動態產生的。 靜態代理使用方式為手動實現一個繼承了IService接口類的代理類Proxy。并在Proxy代理類中手動引用ServiceImpl 功能接口的具體實現類。 代碼: package com.xiaosong.proxy.demo.service;/*** Hello world!**/ public interface IHello {public void sayHello();}package com.xiaosong.proxy.demo.service.impl;import com.xiaosong.proxy.demo.service.IHello;public class Hello implements IHello {public void sayHello() {// TODO Auto-generated method stubSystem.out.println("Hello KuGou!");} }
package com.xiaosong.proxy.demo.jdkproxy;import com.xiaosong.proxy.demo.service.IHello; import com.xiaosong.proxy.demo.service.impl.Hello;public class StaticProxy implements IHello{public Hello hello;public StaticProxy (Hello hello){this.hello=hello;}public void sayHello() {System.out.println("before Hello...");hello.sayHello();System.out.println("after Hello...");}}
2、動態代理:所謂動態是指,不在代碼編譯期確定被加載的類,而是在代碼運行期通過反射的方式來加載。這就是和靜態編譯最根本的區別。 動態代理的使用方式分為3步: (1)寫一個 InvocationHandler接口的實現類實現invoke方法,并在這個實現類中引用一個Object對象(該對象在運行期可能被賦值為各種各樣的ServiceImpl 接口實現類對? 象),在invoke方法通過反射調用Object對象中的方法。 (2)調用Proxy.newProxyInstance(object.getClass().getClassLoader(),?object.getClass().getInterfaces(),?this)?方法,object為1中實現類的對象,獲取一個代理類Proxy。 (3)將(2)中獲取到的Object對象強轉為IService類,并調用IService中的方法,就可以實現對ServiceImpl 的調用了。 package com.xiaosong.proxy.demo.jdkproxy;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler {//代理目標對象public Object object;public MyInvocationHandler(Object object) {// TODO Auto-generated constructor stubthis.object=object;}//獲取代理對象工具方法public Object getProxyObject(){//object.getClass().getClassLoader()確保類加載器為代理目標的加載器return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置方法...");//這里入參要是object,不能是proxy,否則造成死循環,后續會詳細分析原因Object rs = method.invoke(object, args);System.out.println("后置方法...");return rs;}}
相對于靜態代理,動態代理有以下幾個優點: 1、動態代理的代碼量不會隨著接口的增加而無限制的擴大。 2、由于代理類是固定通用的,所以動態代理可以有更多的用途,比如spring AOP,比如RPC遠程調用。 缺點是什么呢? 上述的靜態代理和動態代理的實現都是依賴接口的,如果需要代理一個沒有實現接口的方法,JDK靜態代理就無計可施了。那么問題來了,為什么JDK動態代理必須是依賴接口呢?我們繼續往下看。
轉載于:https://www.cnblogs.com/penglaihaibiandexiaoxiami/p/8312887.html
總結
以上是生活随笔為你收集整理的jdk动态代理源码分析(一)---代理的定义的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]软件保护之注册算法篇
- 下一篇: 回顾JAVA---1.概述及基本语法