2016-03-01 18 views
0

目標:使用AspectJ在執行特定方法後調用靜態方法。使用AspectJ註釋在執行重寫方法後提供邏輯

爲了這個問題,我們稱靜態方法System.out.println和方法onConfigurationChanged

約束:

  1. onConfigurationChanged方法聲明,實施和在一個類被調用我無法控制的(不能被編織)*。
  2. 由於onConfigurationChanged在基類中有一個實現,所以子類可以覆蓋也可以不覆蓋(但在兩種情況下onConfigurationChanged執行後仍應調用System.out.println)。
  3. 使用註釋語法,因爲我的開發環境似乎不支持對本地方面語法的支持。

*注:這是構建一個Android應用程序的情況下,讓有問題的基類實際上是android.app.Activity。很顯然編譯時編織是不可能的。我已經研究了加載時織入,但是我對於在這種情況下如何完成它並且不確定是否需要,因爲它是如此關鍵的代碼路徑。

我目前面臨的主要問題是子類沒有重寫該方法的情況。

我已經嘗試:與onConfigurationChanged簽名指定

  • 執行切入點,以確定@After建議,這就要求System.out.println

    @After("execution(void com.jkhong..*.onConfigurationChanged()) " 
        + "&& !within(DefaultOnConfigurationChangedAspect)") 
    public void onConfigurationChangedExecution() { 
        doDefaultOnConfigurationChanged(); 
    } 
    
    private static void doDefaultOnConfigurationChanged() { 
        System.out.println("Default onConfigurationChanged (mixed in)"); 
    } 
    

在將子類重寫onConfigurationChanged方法的情況下將上述作品。

  • @DeclareMixin瞄準的子類,返回一個匿名類實現調用System.out.println。返回的接口具有與基類中的onConfigurationChanged完全相同的簽名的單個方法。

    public interface OnConfigurationChangedListener { 
        void onConfigurationChanged(); 
    } 
    
    @DeclareMixin("com.jkhong..*.*Activity") 
    public static OnConfigurationChangedListener createDefaultListener() { 
        return new OnConfigurationChangedListener() { 
         @Override 
         public void onConfigurationChanged() { 
          doDefaultOnConfigurationChanged(); 
         } 
        }; 
    } 
    

不幸的是,上述不添加由縱橫提供到不覆蓋onConfigurationChanged子類中的onConfigurationChanged實現。它確實指定子類實現OnConfigurationChangedListener接口,但由於該方法在其父類中實現,因此編譯器不會發出抱怨。 (如果我稍微調整了界面方法的簽名,使其不再匹配,我發現它確實被添加了,但這不是期望的結果。)

任何幫助非常感謝,謝謝。

回答

1

由於技術原因,您必須使用本機語法,因爲declare parents@DeclareParents@DeclareMixin功能更強大。

Eclipse和IntelliJ IDEA都支持AspectJ本地語法。但我不知道NetBeans。你使用哪個IDE?對Eclipse中IDEA提供的高級AspectJ語法功能的最佳支持有一些缺點。但是忽略語法高亮,代碼完成和重構等優秀功能,您可以在任何編輯器中編寫一個方面。

至於你的問題,我想強調的是,我不是一個Android開發者,所以我只是重新您與這兩個僞類使用基本的Android API的功能,從而使我的方面可測試:

把這些變成一個普通的Java項目(或使用原生Android API):

package android.app; 

import android.content.res.Configuration; 

public class Activity { 
    public void onConfigurationChanged (Configuration newConfig) { 
     System.out.println("onConfigurationChanged - default implementation"); 
    } 
} 
package android.content.res; 

public class Configuration {} 

現在我們創建我們的IDE另一個項目,這一次的AspectJ項目。它應該參考上面的小虛擬Android API仿真。

在AspectJ項目,我們創建了兩個Activity子類示範,一個最重要的onConfigurationChanged和一個不重寫它:

package com.jkhong.app; 

import android.app.Activity; 
import android.content.res.Configuration; 

public class OverridingActivity extends Activity { 
    @Override 
    public void onConfigurationChanged(Configuration newConfig) { 
     super.onConfigurationChanged(newConfig); 
     System.out.println("onConfigurationChanged - subclass override"); 
    } 
} 
package com.jkhong.app; 

import android.app.Activity; 

public class NonOverridingActivity extends Activity {} 

隨着一點點的驅動程序就可以顯示會發生什麼:

package com.jkhong.app; 

import android.app.Activity; 
import android.content.res.Configuration; 

public class Application { 
    public static void main(String[] args) { 
     Configuration newConfig = new Configuration(); 
     System.out.println("Activity"); 
     new Activity().onConfigurationChanged(newConfig); 
     System.out.println("\nOverridingActivity"); 
     new OverridingActivity().onConfigurationChanged(newConfig); 
     System.out.println("\nNonOverridingActivity"); 
     new NonOverridingActivity().onConfigurationChanged(newConfig); 
    } 
} 

控制檯日誌如下所示:

Activity 
onConfigurationChanged - default implementation 

OverridingActivity 
onConfigurationChanged - default implementation 
onConfigurationChanged - subclass override 

NonOverridingActivity 
onConfigurationChanged - default implementation 

如您所見,OverridingActivity在做其他事情之前調用其super方法。我建議你總是這樣做。對於NonOverridingActivity,只執行基類的默認實現,如預期的那樣。

現在這裏是一方面解決您的問題:

package com.jkhong.aspect; 

import android.app.Activity; 
import android.content.res.Configuration; 

public aspect ConfigurationChangeInterceptor { 
    public static class DefaultChangeListener extends Activity { 
     @Override 
     public void onConfigurationChanged (Configuration newConfig) { 
      super.onConfigurationChanged(newConfig); 
      doDefaultOnConfigurationChanged(); 
     } 
    } 

    declare parents : Activity+ && !Activity extends DefaultChangeListener; 

    private static void doDefaultOnConfigurationChanged() { 
     System.out.println("onConfigurationChanged - aspect override"); 
    } 
} 

請注意方面如何使用Activity+ && !Activity指定「所有Activity子類,但不Activity本身」,以避免編譯器錯誤,因爲Activity不能擴展其本身並無論如何不會接觸到織布工。

控制檯日誌現在看起來是這樣的:

Activity 
onConfigurationChanged - default implementation 

OverridingActivity 
onConfigurationChanged - default implementation 
onConfigurationChanged - aspect override 
onConfigurationChanged - subclass override 

NonOverridingActivity 
onConfigurationChanged - default implementation 
onConfigurationChanged - aspect override 

所以,現在你有你想要的東西。它觸發的日誌輸出爲NonOverridingActivity,也是OverridingActivity

+0

非常感謝您的詳細信息!我希望不必使用本機方面的文件,但我想這是我唯一的選擇。根據你關於IDE的問題,我使用的是基於IntelliJ IDEA的Android Studio。我將研究可用的AspectJ插件。 –

相關問題