這篇文章帶給大家的內容是關於Java中動態代理和反射機制的詳細介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
反射機制
Java語言提供的一種基礎功能,透過反射,我們可以操作這個類別或對象,例如取得這個類別中的方法、屬性和構造方法等。
動態代理程式:分為JDK動態代理程式、cglib動態代理程式(spring中的動態代理程式)。
靜態代理程式
預先(編譯期間)決定了代理程式與被代理程式之間的關係,也就是說,若代理類別在程式執行前就已經存在了,這種情況就叫靜態代理
動態代理
代理類別在程式執行時所建立的代理方式。也就是說,代理類別並不是在Java程式碼中定義的,而是在運行期間根據我們在Java程式碼中的「指示」動態產生的。
動態代理程式比靜態代理程式的優勢在於:
動態代理程式可以很方便的對代理類別的函數進行統一的處理(invoke),而不是修改每個代理類別的函數,更靈活和擴展。
JDK的動態代理(依賴介面)
在Java的動態代理機制中,有兩個重要的類別或接口,一個是InvocationHandler接口,另一個是Proxy類別。
InvocationHandler介面是給動態代理類別實現的,負責處理被代理對象的操作
Proxy類別是用來建立動態代理類別實例物件的,只有得到這個對象,才能呼叫需要代理的方法。
動態代理的代理類別是在靜態代理類別上進行修改,將動態代理類別實作InvocationHandler接口,重寫Invoke方法,Invoke方法透過傳入的被代理類別方法和參數來執行。
如下實例:
public interface AppService { void createApp(String name); void deleteApp(String name); } //代理类(比如微商代理) public class AppServiceImpl implements AppService{ @Override public void createApp(String name) { System.out.print("App["+name+"] has been created."); } @Override public void deleteApp(String name) { System.out.print("App["+name+"] has been delete."); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LoggerInterceptor implements InvocationHandler { private Object target; //委托类(被代理类)的实例,比如厂家 public LoggerInterceptor(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { System.out.println("Entered "+target.getClass().getName()+"-"+method.getName()+",with arguments{"+args[0]+"}"); Object result = method.invoke(target, args); //调用目标对象的方法 (调用厂家的方法(createApp)及参数(Kevin Test)) System.out.println("Before return:"+result); return result; } }
import java.lang.reflect.Proxy; public class test { public static void main(String[] args) { AppService target = new AppServiceImpl();//生成目标对象 (代理类的对象) //接下来创建代理对象 AppService proxy = (AppService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new LoggerInterceptor(target)); proxy.createApp("Kevin Test1"); proxy.deleteApp("Kevin Test2"); } }/** * 1、jdk的动态代理实现方式是依赖于接口的,首先使用接口来定义好操作规范。 * 2、通过proxy类产生的代理对象调用被代理对象的操作。 * 3、而这个操作又被分发给InvocationHandler接口的invoke方法具体执行 * * 在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。 InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作的,而Proxy是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用那些需要代理的方法。 * * 此方法的参数含义如下 proxy:代表动态代理对象 method:代表正在执行的方法 args:代表当前执行方法传入的实参 返回值:表示当前执行方法的返回值 * * 如上: * 使用了Proxy类的newProxyInstance方法生成代理对象,然后用这个对象去调用createApp()和deleteApp()方法, * 其实系统会将这2个方法分发给invoke()方法区执行。其中proxy对象的类是系统帮我们动态创建了,其实实现了我们的业务接口AppService * */
cglib動態代理程式(繼承方式)
cglib動態代理程式中使用MethodInterceptor來實作動態代理類。
攔截器MethodInterceptor中就是由MethodProxy的InvokSuper方法呼叫代理方法的。
MethodProxy類別產生代理方法和代理程式方法的簽章。
JDK動態代理程式與Cglib動態代理程式的差異:
#1、JDK動態代理程式是實作了被代理物件的接口,Cglib是繼承了被代理物件。
2、Cglib因為是繼承機制,所以無法代理被final修飾的方法。
3、JDK和Cglib都是在運行期間生產字節碼,JDK是直接寫class字節碼,Cglib使用ASM框架寫class字節碼;cglib代理實現更複雜,生成代理類比JDK效率低。
4、JDK調用代理方法,是透過反射實現機制調用,cglib是透過Fashclass機制直接調用方法,效率更高。
Fastcalss機制:
為代理類別和被代理類別產生一個class,這個class會為代理類別或被代理類別的方法分配一個index。
這個index當做一個入參,Fashclass就可以直接定位要呼叫的方法,並且直接進行呼叫。這樣省去了反射調用,所以效率高。
以上是Java中動態代理和反射機制的詳細介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!