MyBatis源码解析【4】反射和动态代理
通過之前的介紹,我們了解了幾個組件的生命周期。
它也是我們重要裝備之一。
今天我們需要搞一件更加強的裝備,叫做反射和動態(tài)代理。
如果沒有這件裝備的話,顯然后面的源碼boss是打不動的。
順便說一下,下面可能會提到一些名詞簡寫,都在之前出現(xiàn)過,所以如果看不明白可以看一下之前的咯。
廢話少說,╭(′▽`)╯
?
什么是代理
首先我們要明白代理是什么樣一個概念。
不要想這個概念有多復(fù)雜,其實很簡單的。代理從中文角度很好理解嘛。它是一個動詞吧,舉個實際的例子,你代理我,幫我抄作業(yè)。
我--->你--->作業(yè)
你代理我,相當(dāng)于我讓你做,或者你幫我做。
最終抄作業(yè)這個事情呢是由你來完成的。嘻嘻。
注意這個例子的兩個關(guān)鍵:
1、我沒有直接操作真實的最終的對象。(我沒有抄作業(yè))
2、你可以提供額外的服務(wù),比如告訴我作業(yè)抄好了,或者明天有什么作業(yè)。
那么認真的講:
通過代理模式,訪問者沒有辦法操作真實的對象,只能通過代理對象去操作真實的對象。代理對象可以提供額外的服務(wù),比操作真實對象更多的服務(wù)。
?
什么是反射
是不是很多人當(dāng)提到這個概念有下面幾個感覺:1、反射學(xué)過沒用過。2、反射很難,但是沒啥用。3、反射很危險,沒事情不要亂用。
如果你有這么幾個概念的話,證明你已經(jīng)對反射有一些學(xué)習(xí)和感覺了(滑稽臉)。
如果沒有的話,我建議呢,還是去好好找個大神的博客或者視頻學(xué)習(xí)一下反射。因為不簡單,聽我一兩句可能不一定明白。
那我們這里用到反射,需要知道這幾個點。
1、在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法。
2、對于任意一個對象,都能夠調(diào)用它的任意方法和屬性;生成動態(tài)代理。
3、通過一些特殊的方法得到對象,calss.forname等
知道這些就可以了。
如果你愿意呢,可以看一下我以前寫的關(guān)于反射的幾個小例子,希望能幫到你:http://www.cnblogs.com/linkstar/p/5744444.html
?
什么是動態(tài)代理
動態(tài)代理其實上面在說代理的時候以及提到了。其實就是動態(tài)的代理嘛。
動態(tài)代理這里介紹兩種:一種使用JDK的反射機制提供的代理,另一種是CGLIB代理。
我們一種種來講。
JDK的動態(tài)代理。
如何實現(xiàn)呢?很簡單,完成兩個類就可以了。
1、服務(wù)類,也就是真正提供服務(wù)的人。
2、代理類,代理做事情的人。
對于JDK的動態(tài)代理的服務(wù)類來說需要額外一個接口開放給代理類哦。
下面是代碼
接口
public interface DemoService {public void demo(); }實現(xiàn)類
public class DemoServiceImpl implements DemoService {public void demo() {System.out.println("Test------------");} }代理類
public class DemoServiceProxy implements InvocationHandler {private Object target;public Object bind(Object target){this.target = target;//利用反射將這個類DemoServiceProxy作為傳入的目標類的代理類return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}//代理方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method : " + method.getName());return method.invoke(target, args);} }測試類
public class DemoServiceTest {public static void main(String[] args) {DemoServiceProxy demoServiceHanler = new DemoServiceProxy();DemoService proxy = (DemoService) demoServiceHanler.bind(new DemoServiceImpl());proxy.demo();} }最后打印結(jié)果
method : demo
Test------------
這里的這幾個類的作用和功能要好好理解哦,因為后面讀源碼的時候需要用到。
然后是CGLIB代理
相對來說就沒有那么復(fù)雜了,只需要一個類就可以了,不需要接口。
public class DemoServiceCglib implements MethodInterceptor {private Object target;public Object getInstance(Object target){this.target = target;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return enhancer.create();}public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("method : " + method.getName());return proxy.invokeSuper(obj, args);} }測試類修改
public class DemoServiceTest {public static void main(String[] args) {/*DemoServiceProxy demoServiceHanler = new DemoServiceProxy();DemoService proxy = (DemoService) demoServiceHanler.bind(new DemoServiceImpl());proxy.demo();*/DemoServiceCglib demoServiceCglib = new DemoServiceCglib();DemoService proxy = (DemoService) demoServiceCglib.getInstance(new DemoServiceImpl());proxy.demo();} }測試結(jié)果相同。
這里就不深究兩種動態(tài)代理的各種參數(shù)啊,方法啊。
我們需要知道的是,在被動態(tài)代理之后,當(dāng)我們調(diào)用原來的方法時候一定調(diào)用一個叫做invoke的方法。
也就是在調(diào)用的前后我們能做很多事情了。
上述在mybatis的源碼中會出現(xiàn),很重要,望理解。
?
至此,裝備都有了,之后就要開始進入難點了。
轉(zhuǎn)載于:https://www.cnblogs.com/linkstar/p/7118784.html
總結(jié)
以上是生活随笔為你收集整理的MyBatis源码解析【4】反射和动态代理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IEnumerable和IEnumera
- 下一篇: C# 填充pdf 模板生成报告