溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

MyBatis反射和動(dòng)態(tài)代理的定義

發(fā)布時(shí)間:2021-09-10 14:35:24 來(lái)源:億速云 閱讀:132 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“MyBatis反射和動(dòng)態(tài)代理的定義”,在日常操作中,相信很多人在MyBatis反射和動(dòng)態(tài)代理的定義問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”MyBatis反射和動(dòng)態(tài)代理的定義”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

理解反射和動(dòng)態(tài)代理
反射

首先看看官網(wǎng)對(duì)反射的定義:

可以通過(guò)java代碼,獲取當(dāng)前加載類的字段、方法、構(gòu)造函數(shù)等信息,并在安全限制內(nèi),使用反射字段、方法、構(gòu)造函數(shù)進(jìn)行操作。

簡(jiǎn)單來(lái)說(shuō),可以在運(yùn)行時(shí)獲得程序中每一個(gè)類型的成員信息。程序中定義的對(duì)象,其類型都是在編譯期確定的,而反射可以動(dòng)態(tài)地創(chuàng)建對(duì)象,并訪問(wèn)或調(diào)用其成員。

動(dòng)態(tài)代理

所謂代理,是一個(gè)人或組織代替另一個(gè)人或組織做事,主要有3個(gè)角色:訪問(wèn)者、代理人、被代理人,訪問(wèn)者經(jīng)由代理人,與被代理人交互,中間會(huì)加入一些自己的處理。

所謂的動(dòng)態(tài)代理,是說(shuō)在編譯時(shí)不需要定義代理類,而是在運(yùn)行時(shí)創(chuàng)建,這個(gè)是關(guān)鍵:在運(yùn)行時(shí)創(chuàng)建代理類。

Class對(duì)象

Class類是一個(gè)實(shí)實(shí)在在的類,存在于java.lang包中,用來(lái)表示運(yùn)行時(shí)類型信息。Class對(duì)象表示自定義類的類型信息,比如創(chuàng)建一個(gè)User類,JVM就會(huì)創(chuàng)建一個(gè)User對(duì)應(yīng)的Class對(duì)象,保存User類相關(guān)的類型信息,該對(duì)象保存在jvm堆中,作為訪問(wèn)方法區(qū)中User類型信息的接口。

在使用自定義類時(shí),會(huì)首先檢查這個(gè)類的Class對(duì)象是否已經(jīng)加載,如果沒有加載,默認(rèn)的類加載器就會(huì)先根據(jù)類名查找.class文件,Class對(duì)象就會(huì)被加載到內(nèi)存。

可以通過(guò)下面3種方法獲取Class對(duì)象:

  • 使用Class類的forName靜態(tài)方法;

  • 直接獲取某一個(gè)對(duì)象的class;

  • 調(diào)用某個(gè)對(duì)象的getClass()方法;

Class對(duì)象是反射的基礎(chǔ),提供了獲取類信息的方法,后面會(huì)介紹。

反射提供的功能

java反射框架主要提供以下內(nèi)容:

  • 在運(yùn)行時(shí)判斷對(duì)象所屬的類;

  • 在運(yùn)行時(shí)創(chuàng)建對(duì)象;

  • 在運(yùn)行時(shí)獲取類包含的成員變量、方法、父類、接口等信息;

  • 在運(yùn)行時(shí)調(diào)用一個(gè)對(duì)象的方法;

下面舉例說(shuō)明相關(guān)功能

創(chuàng)建實(shí)例:

//獲取String所對(duì)應(yīng)的Class對(duì)象
Class<?> c = User.class;
//獲取String類帶一個(gè)String參數(shù)的構(gòu)造器
Constructor constructor = c.getConstructor(String.class);
//根據(jù)構(gòu)造器創(chuàng)建實(shí)例
User user = (User)constructor.newInstance("calm");

獲取方法:

//返回類或接口聲明的所有方法,包括私有的,但不包括繼承的方法
public Method[] getDeclaredMethods() throws SecurityException

//所有public方法,包括繼承的方法
public Method[] getMethods() throws SecurityException

//返回一個(gè)特定的方法,第一個(gè)參數(shù)為方法名稱,后面的參數(shù)為方法參數(shù)對(duì)應(yīng)Class的對(duì)象
public Method getMethod(String name, Class<?>... parameterTypes)

調(diào)用方法:

Class<?> userClass=User.class;
Object obj = userClass.newInstance();
Method method =klass.getMethod("addRole",String.class);
method.invoke(obj,"超級(jí)管理員");
JDK動(dòng)態(tài)代理

JDK本身提供了動(dòng)態(tài)代理的實(shí)現(xiàn),要求被代理者必須實(shí)現(xiàn)接口。

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler h)

第一個(gè)參數(shù)為類加載器,第二個(gè)參數(shù)是被代理者實(shí)現(xiàn)的接口列表,第三個(gè)參數(shù)是實(shí)現(xiàn)了InvocationHandler接口的對(duì)象。

InvocationHandler是一個(gè)接口,用于規(guī)范執(zhí)行被代理者的方法,可在執(zhí)行方法前后,添加公共的處理代碼。生成的動(dòng)態(tài)代理類包含一個(gè)InvocationHandler屬性,調(diào)用對(duì)應(yīng)方法時(shí),會(huì)觸發(fā)invoke方法的調(diào)用。

public class JDKProxy implements InvocationHandler {    

    private Object targetObject;//被代理對(duì)象   

    public Object newProxy(Object targetObject) {        
        this.targetObject = targetObject;     
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}    

    public Object invoke(Object proxy, Method method, Object[] args)//invoke方法    
            throws Throwable {    
        Object ret = null;         
        ret  = method.invoke(targetObject, args);      
        return ret;    
    }    
}

測(cè)試代碼:

JDKProxy jdkProxy=new JDKProxy();
UserService userService = (UserService) 
jdkProxy.newProxy(new UserServiceImp());    
userService.addRole("超級(jí)管理員");

JDK動(dòng)態(tài)代理的基本原理是根據(jù)定義好的規(guī)則,用傳入的接口創(chuàng)建一個(gè)新類。

CGLIB動(dòng)態(tài)代理

JDK動(dòng)態(tài)代理要求必須有接口,CGLIB(Code Generate Library)動(dòng)態(tài)代理沒有這個(gè)要求,它是通過(guò)創(chuàng)建一個(gè)被代理類的子類,然后使用ASM字節(jié)碼庫(kù)修改代碼來(lái)實(shí)現(xiàn)的。

public class CGLibProxy implements MethodInterceptor {    
    private Object targetObject; //被代理對(duì)象

    public Object createProxyObject(Object obj) {    
        this.targetObject = obj;    
        Enhancer enhancer = new Enhancer();    
        enhancer.setSuperclass(obj.getClass());    
        enhancer.setCallback(this);    
        Object proxyObj = enhancer.create();    
        return proxyObj;
    }    

    public Object intercept(Object proxy, Method method, Object[] args,    
            MethodProxy methodProxy) throws Throwable {    
        Object obj = null;       
        obj = method.invoke(targetObject, args);    
        return obj;    
    }       
}

測(cè)試代碼:

CGLibProxy cgLibProxy=new CGLibProxy();
UserService userService = (UserService) 
cgLibProxy.newProxy(new UserServiceImp());    
userService.addRole("超級(jí)管理員");

到此,關(guān)于“MyBatis反射和動(dòng)態(tài)代理的定義”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI