Recipe 15.3. Inheriting Classes into AspectsProblemYou want to refactor an existing class as an aspect by inheriting the existing class's behavior. SolutionUse the extends keyword to declare that the aspect extends the class. DiscussionExample 15-5 shows a pseudo-logging class that represents an existing logging mechanism. The aim is to refactor all existing calls to the logging class from the application and modularize the logging into an aspect that can more flexibly be woven into the application. Example 15-5. A pseudo-traditional logging class representing an existing logging class within the application prior to being refactored for aspectspublic class OOLogging { public void logEntry(String entry) { System.out.println("Entry logged: " + entry); } } Once the existing calls to the class have been refactored out of the application, an aspect can be created to reapply logging to the application, reusing the original logging class through inheritance, as shown in Example 15-6. Example 15-6. Using inheritance of a traditional class to reuse behavior being refactored into an aspectpublic aspect AOLogging extends OOLogging { /* Specifies calling advice whenever a method matching the following rules gets called: Class Name: MyClass Method Name: foo Method Return Type: void Method Parameters: an int followed by a String */ pointcut callPointcut( ) : call(void MyClass.foo(int, String)); // Advice declaration before( ) : callPointcut( ) && !within(AOLogging +) && !within(OOLogging) { this.logEntry(thisJoinPoint.toShortString( )); } }
Figure 15-3 shows the static structure after declaring the aspect shown in Example 15-6. Figure 15-3. Applying reuse using inheritance between aspects and classesAlthough aspects can reuse class behavior using inheritance, this can sometimes be a brittle approach. A more elegant solution would be to perform reuse by aggregation incorporating the logging class as an attribute of the logging aspect. The logging aspect could then be woven against the target application and effectively delegate the logging behavior to the internal instance of the logging class. See AlsoRecipe 4.1 shows the definition of the call(Signature) pointcut; the within(TypePattern) pointcut is described in Recipe 9.1; the NOT(!) operator is described in Recipe 12.4; refactoring can often be achieved using inner aspects, which are discussed in Recipe 15.4. |