Java におけるコード進化パターン (Code Evolution Patterns in Java) - AspectJ
asato shimotaki <asatohan at gmail.com>
最終更新日 : 2008/8/2 (2008/8/2 本ページから分割)
AspectJ 基本関連
アスペクトの追加
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { before() : call( void MyClass.method() ) { System.out.println("before"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
抽象アスペクトの導入
タイプ:リファクタリング
before:
public class MyClass { public void myMethod(String str) { System.out.println("MyClass.myMethod(String) - " + str); } }
public aspect MyAspectA { before(MyClass my, String str) : target(my) && args(str) && call(void MyClass.myMethod(String) ) { System.out.println("before - MyAspectA [" + my + ", " + str + "]"); } }
public aspect MyAspectB { before(MyClass my, String str) : target(my) && args(str) && call(void MyClass.myMethod(String) ) { System.out.println("before - MyAspectB [" + my + ", " + str + "]"); } }after:
public class MyClass { public void myMethod(String str) { System.out.println("MyClass.myMethod(String) - " + str); } }
public abstract aspect AbstractMyAspect { before(MyClass my, String str) : target(my) && args(str) && call(void MyClass.myMethod(String) ) { log(my, str); } protected abstract void log(MyClass my, String str); }
public aspect MyAspectA extends AbstractMyAspect { protected void log(MyClass my, String str) { System.out.println("before - MyAspectA [" + my + ", " + str + "]"); } }
public aspect MyAspectB extends AbstractMyAspect { protected void log(MyClass my, String str) { System.out.println("before - MyAspectB [" + my + ", " + str + "]"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
抽象アスペクトの追加
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public abstract aspect MyAbstractAspect { before() : call( void MyClass.method() ) { primitiveOperation(); } protected abstract void primitiveOperation(); }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
サブアスペクトの追加
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public abstract aspect MyAbstractAspect { protected abstract pointcut pc(); before() : pc() { System.out.println("before"); } }
public aspect MyAspectA extends MyAbstractAspect { protected pointcut pc() : call( MyClass.new() ); }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public abstract aspect MyAbstractAspect { protected abstract pointcut pc(); before() : pc() { System.out.println("before"); } }
public aspect MyAspectA extends MyAbstractAspect { protected pointcut pc() : call( MyClass.new() ); }
public aspect MyAspectB extends MyAbstractAspect { protected pointcut pc() : call( void MyClass.method() ); }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
アスペクトからのアスペクトの抽出
タイプ:リファクタリング
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { before() : call(void MyClass.method()) { System.out.println("MyClass.method() - before"); } before() : call(* MyClass.*(..)) && !within(MyAspect) { System.out.println("tracing - before : " + thisJoinPoint); } after() : call(* MyClass.*(..)) && !within(MyAspect) { System.out.println("tracing - after : " + thisJoinPoint); } }after:
public class MyClass { // 変更なし public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { before() : call(void MyClass.method()) { System.out.println("MyClass.method() - before"); } }
public aspect MyClassTracing { before() : call(* MyClass.*(..)) { System.out.println("tracing - before : " + thisJoinPoint); } after() : call(* MyClass.*(..)) { System.out.println("tracing - after : " + thisJoinPoint); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
アドバイスの追加
タイプ:
before:
public class MyClass { public void method1() { System.out.println("MyClass.method1()"); } public void method2() { System.out.println("MyClass.method2()"); } }
public aspect MyAspect { before() : call(void MyClass.method1()) { System.out.println("before"); } }after:
public class MyClass { // 変更なし public void method1() { System.out.println("MyClass.method1()"); } public void method2() { System.out.println("MyClass.method2()"); } }
public aspect MyAspect { before() : call(void MyClass.method1()) { System.out.println("before"); } before() : call(void MyClass.method2()) { System.out.println("before"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
ポイントカット定義の公開
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { private pointcut methodCall() : call( void MyClass.method() ); before() : methodCall() { System.out.println("before"); } }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { public pointcut methodCall() : call( void MyClass.method() ); before() : methodCall() { System.out.println("before"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
アスペクトへのポイントカットの追加
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
before() : execution(void MyClass.method()) { printBefore(); } private void printBefore() { System.out.println("before"); }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public aspect MyAspect { public pointcut print() : call(void MyAspect.printBefore()); before() : execution(void MyClass.method()) { printBefore(); } private void printBefore() { System.out.println("before"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
AspectJ 関連
Logging アスペクトの導入
public class Component { private int param1; private int param2; public void setParameter1(int param1) { this.param1 = param1; } public void setParameter2(int param2) { this.param2 = param2; } }
public class Main { public static void main(String[] args) throws Exception { int param1 = 5; int param2 = 10; PrintWriter log = new PrintWriter(new FileWriter("log.txt"), true); log.println("param1 = " + param1); log.println("param2 = " + param2); Component comp = new Component(); comp.setParameter1(param1); comp.setParameter2(param2); } }after:
public class Component { // 変更なし private int param1; private int param2; public void setParameter1(int param1) { this.param1 = param1; } public void setParameter2(int param2) { this.param2 = param2; } }
public aspect ParameterLogging { private PrintWriter log; public ParameterLogging() { try { this.log = new PrintWriter(new FileWriter("log.txt"), true); } catch(IOException e) { throw new RuntimeException(e); } } before(int param1) : args(param1) && call(void Component.setParameter1(int)) { log.println("param1 = " + param1); } before(int param2) : args(param2) && call(void Component.setParameter2(int)) { log.println("param2 = " + param2); } }
public class Main { public static void main(String[] args) throws Exception { Component comp = new Component(); comp.setParameter1(5); comp.setParameter2(10); } }
Activation 機能の導入
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect ComponentAspect { before() : call( void Component.method() ) { System.out.println("before"); } }
public class Main { public static void main(String[] args) { Component comp = new Component(); comp.method(); } }実行結果:
before Component.method()after:
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect ComponentAspect { private static boolean isActive = true; public void activate() { isActive = true; } public void deactivate() { isActive = false; } before() : call( void Component.method() ) && if(isActive) { System.out.println("before"); } }
public class Main { public static void main(String[] args) { Component comp = new Component(); comp.method(); ComponentAspect.aspectOf().deactivate(); comp.method(); } }実行結果:
before Component.method() Component.method()
アスペクトによるパラメータの置き換え
public class Main { public static void main(String[] args) { runProgram("defalut"); // ここを直接修正してモードを設定 } public static void runProgram(String mode) { if (mode.equals("verbose")) { System.out.println("verbose mode"); } else { System.out.println("defalut mode"); } } }実行結果:
defalut modeafter:
public class Main { public static void main(String[] args) { runProgram("defalut"); } public static void runProgram(String mode) { if (mode.equals("verbose")) { System.out.println("verbose mode"); } else { System.out.println("defalut mode"); } } }
public aspect ModeAspect { void around(String mode) : args(mode) && call( void Main.runProgram(String) ) { proceed("verbose"); // ここで間接的に修正してモードを設定 } }実行結果:
verbose mode
inter-type 宣言による Marker interface の実装
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public aspect MyAspect { before() : call( void ComponentA.method() ) { System.out.println("before"); } }after:
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public class ComponentB { public void method() { System.out.println("ComponentB.method()"); } }
public aspect MyAspect { interface ComponentInterface { public void method(); } declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; before() : call( void ComponentInterface.method() ) { System.out.println("before"); } }
inter-type 宣言による Marker interface の実装の抽出
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public class ComponentB { public void method() { System.out.println("ComponentB.method()"); } }
public aspect MyAspect { interface ComponentInterface { public void method(); } declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; before() : call( void ComponentInterface.method() ) { System.out.println("MyAspect - before"); } }
public aspect YourAspect { interface ComponentInterface { public void method(); } declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; before() : call( void ComponentInterface.method() ) { System.out.println("YourAspect - before"); } }after:
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public class ComponentB { public void method() { System.out.println("ComponentB.method()"); } }
public interface ComponentInterface { public void method(); }
public aspect ComponentInterfaceDeclareParents { declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; }
public aspect MyAspect { before() : call( void ComponentInterface.method() ) { System.out.println("MyAspect - before"); } }
public aspect YourAspect { before() : call( void ComponentInterface.method() ) { System.out.println("YourAspect - before"); } }
inter-type 宣言による Marker interface の実装 - コンポーネントの追加
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public class ComponentB { public void method() { System.out.println("ComponentB.method()"); } }
public interface ComponentInterface { public void method(); }
public aspect ComponentInterfaceDeclareParents { declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; }
public aspect MyAspect { before() : call( void ComponentInterface.method() ) { System.out.println("MyAspect - before"); } }
public aspect YourAspect { before() : call( void ComponentInterface.method() ) { System.out.println("YourAspect - before"); } }after:
public class ComponentA { public void method() { System.out.println("ComponentA.method()"); } }
public class ComponentB { public void method() { System.out.println("ComponentB.method()"); } }
public class ComponentC { public void method() { System.out.println("ComponentC.method()"); } }
public interface ComponentInterface { public void method(); }
public aspect ComponentInterfaceDeclareParents { declare parents : ComponentA implements ComponentInterface; declare parents : ComponentB implements ComponentInterface; declare parents : ComponentC implements ComponentInterface; }
public aspect MyAspect { before() : call( void ComponentInterface.method() ) { System.out.println("MyAspect - before"); } }
public aspect YourAspect { before() : call( void ComponentInterface.method() ) { System.out.println("YourAspect - before"); } }
todo
or pointcut の追加
public class MyClass { public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public aspect CommonPointcuts { public pointcut methodExecution() : execution( void MyClass.myMethod() ); }
public aspect Logging { before() : CommonPointcuts.methodExecution() { System.out.println("before"); } }after:
public class MyClass { // 変更なし public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public class YourClass { public void yourMethod() { System.out.println("YourClass.yourMethod()"); } }
public aspect CommonPointcuts { public pointcut methodExecution() : execution( void MyClass.myMethod() ) || execution( void YourClass.yourMethod() ); }
public aspect Logging { // 変更なし before() : CommonPointcuts.methodExecution() { System.out.println("before"); } }
todo
重複するポイントカットの移動
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect MyAspect { before() : call( void Component.method() ) { System.out.println("MyAspect - before"); } }after:
public class Component { // 変更なし public void method() { System.out.println("Component.method()"); } }
public aspect ComponentPointcuts { public pointcut callMethod() : call( void Component.method() ); }
public aspect MyAspect { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspect - before"); } }
public aspect YourAspect { before() : ComponentPointcuts.callMethod() { System.out.println("YourAspect - before"); } }
進化パス
関連パターン
参考文献とリソース
todo
ジョインポイントリスナーの追加
public class Component { public void method() { new ComponentJoinPoint(); } }
public class ComponentJoinPoint { }
public aspect MyAspect { before() : call( ComponentJoinPoint.new() ) { System.out.println("MyAspect - before"); } }after:
public class Component { // 変更なし public void method() { new ComponentJoinPoint(); } }
public class ComponentPointcuts { public pointcut componentJoinPoint() : call( ComponentJoinPoint.new() ); }
public aspect MyAspect { before() : ComponentPointcuts.componentJoinPoint() { System.out.println("MyAspect - before"); } }
public aspect YourAspect { before() : ComponentPointcuts.componentJoinPoint() { System.out.println("YourAspect - before"); } }
進化パス
関連パターン
参考文献とリソース
todo
メソッド名変更によるポイントカット定義の修正
タイプ:
before:
public class AlgorithmRunner { public void runMyAlgorithm() { new MyClass().myMethod(); } }
public class MyClass { public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public aspect MyAspect { before() : withincode( void AlgorithmRunner.runMyAlgorithm() ) && call(void MyClass.myMethod() ) { System.out.println("MyAspect - before"); } }
public class Main { public static void main(String[] args) { new AlgorithmRunner().runMyAlgorithm(); } }after:
public interface Algorithm { public void run(); }
public class AlgorithmRunner { private List algorithms = new ArrayList(); public void addAlgorithm(Algorithm algorithm) { algorithms.add(algorithm); } public void run() { for(Iterator itr = algorithms.iterator(); itr.hasNext();) { ( (Algorithm)itr.next() ).run(); } } }
public class MyClass { public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public class MyAlgorithm implements Algorithm { public void run() { new MyClass().myMethod(); } }
public aspect MyAspect { before() : withincode( void MyAlgorithm.run() ) && call(void MyClass.myMethod() ) { System.out.println("MyAspect - before"); } }
public class Main { public static void main(String[] args) { AlgorithmRunner runner = new AlgorithmRunner(); runner.addAlgorithm( new MyAlgorithm() ); runner.run(); } }
進化パス
関連パターン
参考文献とリソース
todo
重複するポイントカット定義の追加
タイプ:
before:
public class Component { private String name; public void method() { System.out.println("Component.method()"); } public void setName(String name) { this.name = name; } public String getName() { return name; } }
public aspect ComponentPointcuts { public pointcut callMethod() : call( void Component.method() ); }
public aspect MyAspect { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspect - method() - before"); } }
public aspect YourAspect { before() : ComponentPointcuts.callMethod() { System.out.println("YourAspect - method() - before"); } }
public class Main { public static void main(String[] args) { Component comp = new Component(); comp.method(); comp.setName("xxx"); } }after:
public class Component { // 変更なし private String name; public void method() { System.out.println("Component.method()"); } public void setName(String name) { this.name = name; } public String getName() { return name; } }
public aspect ComponentPointcuts { public pointcut callMethod() : call( void Component.method() ); public pointcut callSetName() : call( void Component.setName(String) ); }
public aspect MyAspect { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspect - method() - before"); } before() : ComponentPointcuts.callSetName() { System.out.println("MyAspect - setName(String) - before"); } }
public aspect YourAspect { before() : ComponentPointcuts.callMethod() { System.out.println("YourAspect - method() - before"); } before() : ComponentPointcuts.callSetName() { System.out.println("YourAspect - setName(String) - before"); } }
public class Main { // 変更なし public static void main(String[] args) { Component comp = new Component(); comp.method(); comp.setName("xxx"); } }
進化パス
関連パターン
参考文献とリソース
todo
tangled code の抽出
タイプ:Transient Refactoring
before:
public class Main { public static void main(String[] args) { tangledCode(); mainCode(); } private static void tangledCode() { System.out.println("tangled code"); } private static void mainCode() { System.out.println("main code"); } }after:
public class Main { public static void main(String[] args) { mainCode(); } private static void mainCode() { System.out.println("main code"); } }
public aspect TangledCodeAspect { before() : execution(void Main.main(String[])) { System.out.println("tangled code"); } }
サンプルコード:LookAndFeel の初期化
public class Main { public static void main(String[] args) { initLookAndFeel(); // tangled code run(); // main code } private static void initLookAndFeel() { // tangledCode() try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); } catch(Exception e) { } } private static void run() { // mainCode() JFrame f = new JFrame("test"); JPanel pane = new JPanel(); pane.add( new JButton("ok") ); f.getContentPane().add(pane); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } }after:
public class Main { public static void main(String[] args) { run(); } private static void run() { JFrame f = new JFrame("test"); JPanel pane = new JPanel(); pane.add( new JButton("ok") ); f.getContentPane().add(pane); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } }
public aspect LookAndFeelInitialization { before() : execution(void Main.main(String[])) { try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); } catch(Exception e) {} } }もし、AspectJ 5 を使っているのであれば、アノテーションを用いた方が依存がより小さくなります。
public @interface LookAndFeelInit { }
public aspect LookAndFeelInitialization { before() : execution(@LookAndFeelInit * *(..)) { try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); } catch(Exception e) {} } }
public class Main { @LookAndFeelInit public static void main(String[] args) { run(); } private static void run() { JFrame f = new JFrame("test"); JPanel pane = new JPanel(); pane.add( new JButton("ok") ); f.getContentPane().add(pane); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
Event Tracing の導入
タイプ:Refactoring
before:
public interface ComponentListener { public void methodAEntered(); public void methodBEntered(); }
public class Component { private Listlisteners = new ArrayList (); public void addListener(ComponentListener l) { listeners.add(l); } public void removeListener(ComponentListener l) { listeners.remove(l); } public void methodA() { fireMethodAEntered(); System.out.println("Component.methodA()"); } public void methodB() { fireMethodBEntered(); System.out.println("Component.methodB()"); } private void fireMethodAEntered() { for(ComponentListener l : listeners) { l.methodAEntered(); } } private void fireMethodBEntered() { for(ComponentListener l : listeners) { l.methodBEntered(); } } }
public class ComponentMethodCounter implements ComponentListener { private int methodA = 0; private int methodB = 0; public void methodAEntered() { System.out.println("entered : method A"); methodA++; } public void methodBEntered() { System.out.println("entered : method B"); methodB++; } }after:
public interface ComponentListener { // 変更なし public void methodAEntered(); public void methodBEntered(); }
public class Component { // 変更なし private Listlisteners = new ArrayList (); public void addListener(ComponentListener l) { listeners.add(l); } public void removeListener(ComponentListener l) { listeners.remove(l); } public void methodA() { fireMethodAEntered(); System.out.println("Component.methodA()"); } public void methodB() { fireMethodBEntered(); System.out.println("Component.methodB()"); } private void fireMethodAEntered() { for(ComponentListener l : listeners) { l.methodAEntered(); } } private void fireMethodBEntered() { for(ComponentListener l : listeners) { l.methodBEntered(); } } }
public class ComponentMethodCounter implements ComponentListener { private int methodA = 0; private int methodB = 0; public void methodAEntered() { methodA++; } public void methodBEntered() { methodB++; } }
public aspect EventTracing { before () : execution(* ComponentListener.*(..) ) { System.out.println("enter " + thisJoinPoint.getSignature().getName()); } }
サンプルコード
import java.awt.event.KeyEvent; import java.awt.event.KeyListener; public class KeyCounter implements KeyListener { private int pressed; private int released; private int typed; public void keyPressed(KeyEvent e) { pressed++; } public void keyReleased(KeyEvent e) { released++; } public void keyTyped(KeyEvent e) { typed++; } // その他のメソッド }
public aspect EventTracing { before () : execution(* java.awt.event.KeyListener.*(..) ) { System.out.println("enter " + thisJoinPoint.getSignature().getName()); } }
public class Main { public static void main(String[] args) { JPanel pane = new JPanel(); pane.addKeyListener(new KeyCounter()); pane.setFocusable(true); JFrame frame = new JFrame("test"); frame.getContentPane().add(pane); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
トレースされる Event Listener の追加
タイプ:
before:
public interface ComponentListener { public void methodAEntered(); public void methodBEntered(); }
public class Component { private Listlisteners = new ArrayList (); public void addListener(ComponentListener l) { listeners.add(l); } public void removeListener(ComponentListener l) { listeners.remove(l); } public void methodA() { fireMethodAEntered(); System.out.println("Component.methodA()"); } public void methodB() { fireMethodBEntered(); System.out.println("Component.methodB()"); } private void fireMethodAEntered() { for(ComponentListener l : listeners) { l.methodAEntered(); } } private void fireMethodBEntered() { for(ComponentListener l : listeners) { l.methodBEntered(); } } }
public class ComponentMethodCounter implements ComponentListener { private int methodA = 0; private int methodB = 0; public void methodAEntered() { methodA++; } public void methodBEntered() { methodB++; } }
public aspect EventTracing { before () : execution(* ComponentListener.*(..) ) { System.out.println("enter " + thisJoinPoint.getSignature().getName()); } }after:
public interface ComponentListener { // 変更なし public void methodAEntered(); public void methodBEntered(); }
public class Component { // 変更なし private Listlisteners = new ArrayList (); public void addListener(ComponentListener l) { listeners.add(l); } public void removeListener(ComponentListener l) { listeners.remove(l); } public void methodA() { fireMethodAEntered(); System.out.println("Component.methodA()"); } public void methodB() { fireMethodBEntered(); System.out.println("Component.methodB()"); } private void fireMethodAEntered() { for(ComponentListener l : listeners) { l.methodAEntered(); } } private void fireMethodBEntered() { for(ComponentListener l : listeners) { l.methodBEntered(); } } }
public class ComponentMethodCounter implements ComponentListener { // // 変更なし private int methodA = 0; private int methodB = 0; public void methodAEntered() { methodA++; } public void methodBEntered() { methodB++; } }
public interface MyClassListener { public void myMethodAInvoked(); public void myMethodBInvoked(); }
public class MyClass { private Listlisteners = new ArrayList (); public void addListener(MyClassListener l) { listeners.add(l); } public void removeListener(MyClassListener l) { listeners.remove(l); } public void myMethodA() { fireMyMethodAInvoked(); System.out.println("Component.methodA()"); } public void myMethodB() { fireMyMethodBInvoked(); System.out.println("Component.methodB()"); } private void fireMyMethodAInvoked() { for(MyClassListener l : listeners) { l.myMethodAInvoked(); } } private void fireMyMethodBInvoked() { for(MyClassListener l : listeners) { l.myMethodBInvoked(); } } }
public class MyClassMethodCounter implements MyClassListener { private int myMethodA = 0; private int myMethodB = 0; public void myMethodAInvoked() { myMethodA++; } public void myMethodBInvoked() { myMethodB++; } // その他のメソッド }
public aspect EventTracing { private pointcut tracedEvent() : execution(* ComponentListener.*(..) ) || execution(* MyClassListener.*(..) ); before () : tracedEvent() { System.out.println("enter " + thisJoinPoint.getSignature().getName()); } }
サンプルコード
import java.awt.event.KeyEvent; import java.awt.event.KeyListener; public class KeyCounter implements KeyListener { private int pressed; private int released; private int typed; public void keyPressed(KeyEvent e) { pressed++; } public void keyReleased(KeyEvent e) { released++; } public void keyTyped(KeyEvent e) { typed++; } // その他のメソッド }
import java.awt.event.MouseEvent; import java.awt.event.MouseListener; public class MouseCounter implements MouseListener { private int clicked; private int entered; private int exited; private int pressed; private int released; public void mouseClicked(MouseEvent e) { clicked++; } public void mouseEntered(MouseEvent e) { entered++; } public void mouseExited(MouseEvent e) { exited++; } public void mousePressed(MouseEvent e) { pressed++; } public void mouseReleased(MouseEvent e) { released++; } }
public aspect EventTracing { private pointcut tracedEvent() : execution(* java.awt.event.KeyListener.*(..) ) || execution(* java.awt.event.MouseListener.*(..) ); before () : tracedEvent() { System.out.println("enter " + thisJoinPoint.getSignature().getName()); } }
public class Main { public static void main(String[] args) { JPanel pane = new JPanel(); pane.addKeyListener(new KeyCounter()); pane.addMouseListener(new MouseCounter()); pane.setFocusable(true); JFrame frame = new JFrame("test"); frame.getContentPane().add(pane); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
参考文献とリソース
進化パス
関連パターン
参考文献とリソース
todo
ポイントカットアスペクト - アスペクトの追加
タイプ:機能追加
before:
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect ComponentPointcuts { public pointcut callMethod() : call( void Component.method() ); }
public aspect MyAspectA { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspectA - before"); } }
public aspect MyAspectB { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspectB - before"); } }after:
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect ComponentPointcuts { public pointcut callMethod() : call( void Component.method() ); }
public aspect MyAspectA { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspectA - before"); } }
public aspect MyAspectB { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspectB - before"); } }
public aspect MyAspectC { before() : ComponentPointcuts.callMethod() { System.out.println("MyAspectC - before"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
アスペクトへのコンテキストアノテーションの付加
タイプ:
before:
public class MyClass { public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public class YourClass { public void yourMethod() { System.out.println("YourClass.yourMethod()"); } }
public aspect MyAspect { before() : call(void MyClass.myMethod()) { System.out.println("MyAspect"); new YourClass().yourMethod(); } }after:
public class MyClass { public void myMethod() { System.out.println("MyClass.myMethod()"); } }
public class YourClass { public void yourMethod() { System.out.println("YourClass.yourMethod()"); } }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ContextAnnotation { public String value(); }
public aspect ContextAnnotationAspect { before(ContextAnnotation context) : @within(context) && call(void YourClass.yourMethod()) { System.out.println(context.value()); } }
@ContextAnnotation("MyAspect") public aspect MyAspect { before() : call(void MyClass.myMethod()) { new YourClass().yourMethod(); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
Template Advice - Concrete Aspect の追加
タイプ:
before:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public abstract aspect MyAbstractAspect { before() : call( void MyClass.method() ) { primitiveOperation(); } protected abstract void primitiveOperation(); }
public aspect MyConcreteAspectA extends MyAbstractAspect { protected void primitiveOperation() { System.out.println("MyConcreteAspectA.primitiveOperation()"); } }after:
public class MyClass { public void method() { System.out.println("MyClass.method()"); } }
public abstract aspect MyAbstractAspect { before() : call( void MyClass.method() ) { primitiveOperation(); } protected abstract void primitiveOperation(); }
public aspect MyConcreteAspectA extends MyAbstractAspect { protected void primitiveOperation() { System.out.println("MyConcreteAspectA.primitiveOperation()"); } }
public aspect MyConcreteAspectB extends MyAbstractAspect { protected void primitiveOperation() { System.out.println("MyConcreteAspectB.primitiveOperation()"); } }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
アノテーションによる interface の実装
タイプ:
before:
public interface MyInterface { }
public aspect MyInterfaceImplementation { public void MyInterface.method() { System.out.println("method"); } }
public class MyClass implements MyInterface { }after:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyAnnotation { }
public interface MyInterface { }
public aspect MyInterfaceImplementation { public void MyInterface.method() { System.out.println("method"); } }
public aspect MyAspect { declare parents : (@MyAnnotation *) implements MyInterface; }
@MyAnnotation public class MyClass { }
参考文献とリソース
進化パス
パターン関係
関連パターン
参考文献とリソース
todo
参考文献とリソース
更新履歴
todo