溫馨提示×

溫馨提示×

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

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

Java中怎么增強一個類的功能

發(fā)布時間:2021-07-01 14:50:21 來源:億速云 閱讀:109 作者:Leah 欄目:大數(shù)據(jù)

Java中怎么增強一個類的功能,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

首先第一種,直接在方法中寫上要添加的功能,這種方式最不推薦,因為它違反了java代碼“對擴(kuò)展開放,對修改關(guān)閉”的原則,會影響之前代碼的使用,而且后期維護(hù)也非常麻煩。

第二種,使用繼承,提供一個類繼承當(dāng)前類,重寫要增強的方法,可以實現(xiàn)對功能的添加或增強,繼承的方式不影響原來類的使用,而且代碼實現(xiàn)簡單,但是只能增強一個類的功能,不能批量增強一類事物的功能。如果多個類想要同時修改功能,就要寫很多子類,這樣會造成代碼冗余,而且不利于后期的維護(hù)。

第三種,使用裝飾器模式,舉例,這里有一個Singer類,實現(xiàn)了Sing接口,現(xiàn)在想要對Singer類的sing方法增強,代碼如下:

  1. public interface SingAble {  

  2.     public void sing();  

  3. }  

  1. public class Singer implements SingAble {  

  2.     @Override  

  3.     public void sing() {  

  4.         System.out.println("the original sing!");  

  5.     }  

  6. }  

  1. public class Decorator implements SingAble {  

  2.     private SingAble singer;   

  3.     public Decorator(SingAble singer){  

  4.         this.singer = singer;  

  5.     }  

  6.     @Override  

  7.     public void sing() {  

  8.         System.out.println("before sing...");  

  9.         Singer.sing();  

  10.         System.out.println("after sing...");  

  11.     }  

  12. }  

  1. public class DecoratorTest {  

  2.     public static void main(String[] args) {  

  3.         SingAble singer = new Singer();  

  4.         SingAble obj = new Decorator(singer);  

  5.         obj.sing();  

  6.     }  

  7. }  

輸出:

before sing...

sing a song...

after sing...

裝飾器模式可以動態(tài)地為一類事物增強功能,而且可以動態(tài)的撤銷,而繼承的功能是靜態(tài)的,并不能動態(tài)增刪。

第五種,使用代理模式,代碼如下:

  1. public interface SingAble{  

  2.     public void sing();  

  3. }  

  1. public class Singer implements SIngAble{  

  2.     @Override  

  3.     public void sing() {  

  4.         System.out.println("sing a song...");  

  5.     }  

  6. }  

  1. public class Proxy implements SingAble{  

  2.     private SingAble singer;  

  3.     public Proxy(){  

  4.         this.singer = new Singer();  

  5.     }  

  6.     @Override  

  7.     public void sing() {  

  8.         before();  

  9.         singer.sing();  

  10.         atfer();  

  11. }  

  12. private void before() {  

  13.         System.out.println("before sing...");  

  14.     } 

  15.     private void atfer() {  

  16.         System.out.println("after sing...");  

  17.     }  

  18. }  

  1. public class ProxyTest {  

  2.     public static void main(String[] args) {  

  3.         SingAble singer = new Proxy();  

  4.         singer.sing();  

  5.     }  

  6. }  

輸出:

before sing...

sing a song...

after sing...

代理模式與裝飾器模式看似很相像,實際上還是有區(qū)別的,裝飾器模式以對客戶端透明的方式擴(kuò)展對象的功能,是繼承關(guān)系的一個替代方案,其偏重點在為裝飾的對象增強功能,然而代理模式更偏向于控制對對象的訪問。代理類就像一個中介,可以對它的客戶隱藏一個對象的具體信息。使用代理模式的時候直接在代理類中創(chuàng)建一個對象的實例,因此代理類和真實對象之間的的關(guān)系在編譯時就已經(jīng)確定。而使用裝飾器模式的時候,通常是將原始對象作為參數(shù)傳入。

代理模式同樣可以批量增加一類事物的功能,同時對功能的劃分更為清晰,便于后期維護(hù),這一點在動態(tài)代理中尤為明顯。動態(tài)代理通過反射可以同時對多個方法做處理,而如果使用裝飾者模式,方法較多時,裝飾器類就會變得復(fù)雜。

動態(tài)代理分為jdk代理和cglib代理兩種方式,其中jdk的動態(tài)代理是基于接口實現(xiàn),被代理對象必須實現(xiàn)接口,而cglib是基于父類實現(xiàn),更具有普適性,下面分別使用jdk與cglib 方式實現(xiàn)對SInger類的增強,代碼如下:

jdk方式:

  1. public class Singer_proxy {

  2.     public static void main(String[] args) {

  3.         final Singer singer = new Singer();

  4.         Sing proxy = (Sing) Proxy.newProxyInstance(singer.getClass().getClassLoader(), singer.getClass().getInterfaces(), new InvocationHandler() {

  5.             @Override

  6.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

  7.                 System.out.println("宣傳。。。");//此處可抽取方法,做到業(yè)務(wù)之間隔離

  8.                 Object invoke = method.invoke(singer, args);

  9.                 System.out.println("收場。。。");//同上

  10.                 return invoke;

  11.             }

  12.         });

  13.         proxy.song();

  14.     }

  15. }

cglib方式:

  1. public class Singer_proxy {

  2.     public static void main(String[] args) {

  3.         final Singer singer = new Singer();

  4.         Enhancer enhancer = new Enhancer();

  5.         enhancer.setSuperclass(Singer.class);

  6.         enhancer.setCallback(new MethodInterceptor() {

  7.             @Override

  8.             public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

  9.                 System.out.println("宣傳。。。");

  10.                 Object invoke = method.invoke(singer, objects);

  11.                 System.out.println("收場。。。");

  12.                 return invoke;

  13.             }

  14.         });

  15.         Singer proxy = (Singer) enhancer.create();

  16.         proxy.sing();

  17.     }

  18. }

Spring的AOP( Aspect Oriented Programming )面向切面編程,其底層就是使用動態(tài)代理來實現(xiàn)的,Spring內(nèi)部集成了cglib,會根據(jù)對象是否實現(xiàn)接口來判斷使用jdk方式還是cglib方式來實現(xiàn)對象的代理,當(dāng)然也可以顯式的設(shè)置為始終使用cglib方式代理。

AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度大大降低,同時提高程序的可重用性,提高了開發(fā)的效率,AOP形象地體現(xiàn)出了java代碼“高內(nèi)聚,低耦合”的思想。

Spring的AOP封裝了動態(tài)代理,通過配置的方式,就可以實現(xiàn)在運行期間動態(tài)的生成代理對象,代理對象方法執(zhí)行時進(jìn)行增強功能的介入,在去調(diào)用目標(biāo)對象的方法,從而完成功能的增強。通過配置“前置通知”、“后置通知”、“環(huán)繞通知”、“異常拋出通知”、“最終通知”五種“通知”類型(“通知”為面向切面編程中的術(shù)語,攔截到要增強的對象的方法時,要做的事情就稱為“通知”),決定在具體什么位置添加對應(yīng)功能,實際上環(huán)繞通知就可以實現(xiàn)其他所有通知的功能,代碼如下所示,所以很多時候我們直接使用環(huán)繞通知。

  1. public Object around(ProceedingJoinPoint pjp) throws Throwable {

  2.         try {

  3.             System.out.println("前置通知。。。");

  4.             Object[] args = pjp.getArgs();

  5.             Object proceed = pjp.proceed(args);

  6.             System.out.println("后置通知。。。");

  7.             return proceed;

  8.         } catch (Exception e) {

  9.             e.printStackTrace();

  10.             System.out.println("異常拋出通知。。。");

  11.         }finally{

  12.             System.out.println("最終通知。。。");

  13.         }

  14.         return null;

  15. }

Spring的聲明式事務(wù)管理,其底層也是通過AOP實現(xiàn),使用的就是環(huán)繞通知,可以非常方便地對各種業(yè)務(wù)統(tǒng)一做事務(wù)管理。由于動態(tài)代理良好的解耦性,其實很多框架的都會使用到這項技術(shù)。

看完上述內(nèi)容,你們掌握J(rèn)ava中怎么增強一個類的功能的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

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

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

AI