您好,登錄后才能下訂單哦!
Java中怎么增強一個類的功能,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
首先第一種,直接在方法中寫上要添加的功能,這種方式最不推薦,因為它違反了java代碼“對擴展開放,對修改關閉”的原則,會影響之前代碼的使用,而且后期維護也非常麻煩。
第二種,使用繼承,提供一個類繼承當前類,重寫要增強的方法,可以實現對功能的添加或增強,繼承的方式不影響原來類的使用,而且代碼實現簡單,但是只能增強一個類的功能,不能批量增強一類事物的功能。如果多個類想要同時修改功能,就要寫很多子類,這樣會造成代碼冗余,而且不利于后期的維護。
第三種,使用裝飾器模式,舉例,這里有一個Singer類,實現了Sing接口,現在想要對Singer類的sing方法增強,代碼如下:
public interface SingAble {
public void sing();
}
public class Singer implements SingAble {
@Override
public void sing() {
System.out.println("the original sing!");
}
}
public class Decorator implements SingAble {
private SingAble singer;
public Decorator(SingAble singer){
this.singer = singer;
}
@Override
public void sing() {
System.out.println("before sing...");
Singer.sing();
System.out.println("after sing...");
}
}
public class DecoratorTest {
public static void main(String[] args) {
SingAble singer = new Singer();
SingAble obj = new Decorator(singer);
obj.sing();
}
}
輸出:
before sing...
sing a song...
after sing...
裝飾器模式可以動態地為一類事物增強功能,而且可以動態的撤銷,而繼承的功能是靜態的,并不能動態增刪。
第五種,使用代理模式,代碼如下:
public interface SingAble{
public void sing();
}
public class Singer implements SIngAble{
@Override
public void sing() {
System.out.println("sing a song...");
}
}
public class Proxy implements SingAble{
private SingAble singer;
public Proxy(){
this.singer = new Singer();
}
@Override
public void sing() {
before();
singer.sing();
atfer();
}
private void before() {
System.out.println("before sing...");
}
private void atfer() {
System.out.println("after sing...");
}
}
public class ProxyTest {
public static void main(String[] args) {
SingAble singer = new Proxy();
singer.sing();
}
}
輸出:
before sing...
sing a song...
after sing...
代理模式與裝飾器模式看似很相像,實際上還是有區別的,裝飾器模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案,其偏重點在為裝飾的對象增強功能,然而代理模式更偏向于控制對對象的訪問。代理類就像一個中介,可以對它的客戶隱藏一個對象的具體信息。使用代理模式的時候直接在代理類中創建一個對象的實例,因此代理類和真實對象之間的的關系在編譯時就已經確定。而使用裝飾器模式的時候,通常是將原始對象作為參數傳入。
代理模式同樣可以批量增加一類事物的功能,同時對功能的劃分更為清晰,便于后期維護,這一點在動態代理中尤為明顯。動態代理通過反射可以同時對多個方法做處理,而如果使用裝飾者模式,方法較多時,裝飾器類就會變得復雜。
動態代理分為jdk代理和cglib代理兩種方式,其中jdk的動態代理是基于接口實現,被代理對象必須實現接口,而cglib是基于父類實現,更具有普適性,下面分別使用jdk與cglib 方式實現對SInger類的增強,代碼如下:
jdk方式:
public class Singer_proxy {
public static void main(String[] args) {
final Singer singer = new Singer();
Sing proxy = (Sing) Proxy.newProxyInstance(singer.getClass().getClassLoader(), singer.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("宣傳。。。");//此處可抽取方法,做到業務之間隔離
Object invoke = method.invoke(singer, args);
System.out.println("收場。。。");//同上
return invoke;
}
});
proxy.song();
}
}
cglib方式:
public class Singer_proxy {
public static void main(String[] args) {
final Singer singer = new Singer();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Singer.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("宣傳。。。");
Object invoke = method.invoke(singer, objects);
System.out.println("收場。。。");
return invoke;
}
});
Singer proxy = (Singer) enhancer.create();
proxy.sing();
}
}
Spring的AOP( Aspect Oriented Programming )面向切面編程,其底層就是使用動態代理來實現的,Spring內部集成了cglib,會根據對象是否實現接口來判斷使用jdk方式還是cglib方式來實現對象的代理,當然也可以顯式的設置為始終使用cglib方式代理。
AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度大大降低,同時提高程序的可重用性,提高了開發的效率,AOP形象地體現出了java代碼“高內聚,低耦合”的思想。
Spring的AOP封裝了動態代理,通過配置的方式,就可以實現在運行期間動態的生成代理對象,代理對象方法執行時進行增強功能的介入,在去調用目標對象的方法,從而完成功能的增強。通過配置“前置通知”、“后置通知”、“環繞通知”、“異常拋出通知”、“最終通知”五種“通知”類型(“通知”為面向切面編程中的術語,攔截到要增強的對象的方法時,要做的事情就稱為“通知”),決定在具體什么位置添加對應功能,實際上環繞通知就可以實現其他所有通知的功能,代碼如下所示,所以很多時候我們直接使用環繞通知。
public Object around(ProceedingJoinPoint pjp) throws Throwable {
try {
System.out.println("前置通知。。。");
Object[] args = pjp.getArgs();
Object proceed = pjp.proceed(args);
System.out.println("后置通知。。。");
return proceed;
} catch (Exception e) {
e.printStackTrace();
System.out.println("異常拋出通知。。。");
}finally{
System.out.println("最終通知。。。");
}
return null;
}
Spring的聲明式事務管理,其底層也是通過AOP實現,使用的就是環繞通知,可以非常方便地對各種業務統一做事務管理。由于動態代理良好的解耦性,其實很多框架的都會使用到這項技術。
看完上述內容,你們掌握Java中怎么增強一個類的功能的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。