日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

java动态代理【一】

發(fā)布時(shí)間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java动态代理【一】 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
java動(dòng)態(tài)代理的定義:為其他目標(biāo)類的方法增加切面的邏輯,即在執(zhí)行目標(biāo)類方法的時(shí)候,先去執(zhí)行一段如校驗(yàn)檢測(cè)的邏輯代碼。java通俗一點(diǎn)就是生成一個(gè)繼承目標(biāo)類的子類,并在每個(gè)調(diào)用方法都添加一段邏輯。
應(yīng)用場(chǎng)景:當(dāng)我們從別的項(xiàng)目遷移過來的代碼進(jìn)行修改的時(shí)候,如果有一個(gè)需求是當(dāng)要執(zhí)行某個(gè)業(yè)務(wù)類的所有方法前,需要校驗(yàn)其權(quán)限或其他的時(shí)候,如果這個(gè)類是源代碼,我們還可以在類的基礎(chǔ)上對(duì)每個(gè)方法區(qū)更改,但若是打包成jar包的類,若該類有接口還可以實(shí)現(xiàn)一個(gè)代理模式創(chuàng)建一個(gè)代理類,沒有接口就比較麻煩,但接口一旦多起來,那編寫的話也比較麻煩。這時(shí)我們就需要用到動(dòng)態(tài)代理,由jdk動(dòng)態(tài)創(chuàng)建一個(gè)proxy類,我們通過proxy類來調(diào)用目標(biāo)類的方法。
動(dòng)態(tài)代理的實(shí)現(xiàn)有三種方法:1、使用代理模式。1)創(chuàng)建一個(gè)Star(明星)類,其實(shí)現(xiàn)了Speak,Eat接口

  1. package cglib;
  2. public class Star implements Speak,Eat{
  3. @Override
  4. public void say() {
  5. // TODO Auto-generated method stub
  6. System.out.println("i am a star");
  7. }
  8. @Override
  9. public void eat() {
  10. // TODO Auto-generated method stub
  11. System.out.println("star eats some fruit");
  12. }
  13. }
2)創(chuàng)建一個(gè)Broker(經(jīng)紀(jì)人)類,其實(shí)現(xiàn)了Speak接口,如下代碼:
  1. package cglib;
  2. //裝飾器模式
  3. public class Broker implements Speak{
  4. private Speak speak;
  5. public Broker(Speak speak){
  6. this.speak=speak;
  7. }
  8. @Override
  9. public void say() {
  10. // TODO Auto-generated method stub
  11. speak.say();
  12. }
  13. }

3)測(cè)試代碼:
? ? ? ?輸出I am Star! 一個(gè)經(jīng)紀(jì)人可以代理不同的明星表述,這在現(xiàn)實(shí)中是符合的。2、使用JDK動(dòng)態(tài)代理(原理是通過映射,動(dòng)態(tài)生成java字節(jié)碼Proxy類)1)同樣以Star類為目標(biāo)類,實(shí)現(xiàn)JDK動(dòng)態(tài)代理需要實(shí)現(xiàn)InvocationHandler接口,如下:
  1. package cglib;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. public class JDKDynamicProxy implements InvocationHandler{
  6. private Object speak;
  7. private JDKDynamicProxy(Object speak){
  8. //傳入star對(duì)象
  9. this.speak=speak;
  10. }
  11. //創(chuàng)建一個(gè)靜態(tài)方法,生成代理類,
  12. public static Object newProxyInstance(Object speak){
  13. System.out.println(JDKDynamicProxy.class.getClassLoader().toString());
  14. return Proxy.newProxyInstance(JDKDynamicProxy.class.getClassLoader(),new Class[]{Speak.class,Eat.class}, new JDKDynamicProxy(speak));
  15. }
  16. //覆蓋InvocationHandler的invoke方法,從參數(shù)可以看出,這個(gè)方法明顯使用了jdk的方法映射來調(diào)用Star的方法,在調(diào)用Star的方法前后,我們都可以增加自己的邏輯代碼
  17. @Override
  18. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  19. // TODO Auto-generated method stub
  20. System.out.println("call the JDKDynamicProxy");
  21. return method.invoke(speak, args);
  22. }
  23. }

2)測(cè)試類
  1. package cglib;
  2. import java.lang.reflect.Constructor;
  3. public class ProxyTest {
  4. public static void main(String[] args) {
  5. //裝飾者模式
  6. Star star=new Star();
  7. Speak b=new Broker(star);
  8. b.say();
  9. //jdk動(dòng)態(tài)代理模式
  10. Speak s=(Speak) JDKDynamicProxy.newProxyInstance(star);
  11. s.say();
  12. Eat e=(Eat) JDKDynamicProxy.newProxyInstance(star);
  13. e.eat();
  14. //CGlib動(dòng)態(tài)代理
  15. Speak sp=CGProxy.newCGproxyInstance(Star.class);
  16. sp.say();
  17. }
  18. }
可以看出在調(diào)用Star的say()方法之前,調(diào)用了JDKDynamicProxy 的invoke方法。3、使用CGLib動(dòng)態(tài)代理(原理使用了asm)
? ? ? ? 1)CGProxy類,因?yàn)槭欠椒〝r截,故實(shí)現(xiàn)的是MethodInterceptor 接口,下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)方法。
  1. package cglib;
  2. import java.lang.reflect.Method;
  3. import net.sf.cglib.proxy.Enhancer;
  4. import net.sf.cglib.proxy.MethodInterceptor;
  5. import net.sf.cglib.proxy.MethodProxy;
  6. public class CGProxy implements MethodInterceptor {
  7. public static <T extends Speak> Speak newCGproxyInstance(Class<T> superClass){
  8. Enhancer en=new Enhancer();
  9. en.setSuperclass(superClass);
  10. en.setCallback(new CGProxy());
  11. return (Speak)en.create();
  12. }
  13. @Override
  14. public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
  15. // TODO Auto-generated method stub
  16. System.out.println("call the CGProxy");
  17. return arg3.invokeSuper(arg0, arg2);
  18. }
  19. }
看代碼和JDK動(dòng)態(tài)代理的寫法差不多,但其內(nèi)部實(shí)現(xiàn)的原理卻不同。明顯的區(qū)別從代碼可以看出,JDK動(dòng)態(tài)代理要傳入目標(biāo)類的接口作為參數(shù),所以目標(biāo)類必須要有一個(gè)統(tǒng)一的接口,即如上的Speak,Eat接口,這就使得JDK動(dòng)態(tài)代理有一定的局限性。而CGlib從代碼看出,傳入的是Class,不是接口,使用范圍更廣一些。


下一章探討一下JDK動(dòng)態(tài)代理內(nèi)部的實(shí)現(xiàn)原理。



null

轉(zhuǎn)載于:https://www.cnblogs.com/zhenyimo/p/6837321.html

總結(jié)

以上是生活随笔為你收集整理的java动态代理【一】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。