CSC/ECE 517 Fall 2009/wiki29 VB: Difference between revisions
Line 106: | Line 106: | ||
Join points: | Join points: | ||
• Object receives method/constructor call | • Object receives method/constructor call | ||
• Field accessed (if access is via getter/setter meth) | • Field accessed (if access is via getter/setter meth) | ||
Advices: before (pre), after returning and after throwing (post) | |||
Advices can access: | |||
• Object and method receiving call | |||
• Arguments to call | |||
• Return value | |||
• exceptions raised. | |||
Aspects: classes inheriting Aspect. | Aspects: classes inheriting Aspect. | ||
Supports "abstract" Aspects and overriding between advices. | |||
Wildcards (really regexps) can be used in pointcut designators, ie. to specify classes and methods to wrap advice's to. | |||
Pointcut parameters. | |||
Revision as of 21:49, 9 October 2009
Aspect Oriented Programming - An Introduction
When Object-Oriented (OO) programming was entering into the field of software development, it changed the way how software was developed. The software systems began to be viewed as groups of entities and the interaction between those entities, which allowed them to tackle larger, more complicated systems and develop them in less time than ever before. However, OO programming is static, and a thus a change in requirements could have a brought a major impact on development time lines.
Aspect-Oriented Programming (AOP) complements OO programming by allowing the developer to dynamically modify the static OO model to create a system that can grow to meet new requirements. Just as objects in the real world can change their states during their lifecycles, an application can adopt new characteristics as it develops.
For example, we develop a web application where a servlet accepts the values of an HTML form, binds them to an object, passes them into the application to be processed, and then returns a response to the user. This basic functionality of the servlet may be very simple, and can be fulfilled with minimum amount of code. But, by the time secondary requirements such as exception handling, security, and logging have been implemented , the size of the code increases to about three times of original. Having said that, it is not mandatory for the servlet to know about the logging or security mechanisms being used, and hence can be called as secondary requirements. Its primary function is to just accept input and process it.
Using AOP , we can dynamically modify our static model to include the code required to fulfill the secondary requirements without having to modify the original static model. We can also keep this additional code in a single location rather than having to scatter it across the existing model, as we would have to if we were using OO on its own. [1]
Terminologies used in Aspect Oriented Programming
Just as the important facets of OOP are inheritance, encapsulation, and polymorphism, the components of AOP are join points, pointcut, advice, and introduction.
Here are the definitions of some of the standard terms that would be required to understand AOP concepts.
1.Cross-cutting concerns: Even though most classes in an OO model will perform a single, specific function, they often share common, secondary requirements with other classes. For example, we may want to add logging to classes within the data-access layer and also to classes in the UI layer whenever a thread enters or exits a method. Even though the primary functionality of each class is very different, the code needed to perform the secondary functionality is often identical.
2.Advice: Advice is the extra code that we want to add to our already existing model.
3.Point-cut: Point-cut is the point of execution in the application at which cross-cutting concern needs to be applied.
4.Aspect: Aspect is the combination of the point-cut and the advice.
The other terms that appear often in AOP are introductions (where interfaces/methods/fields can be added to existing classes). These hold tremendous potential for developers. [2]
AspectJ
AOP has been implemented in different languages, among them Smalltalk and Java. The Java implementation of AOP is called AspectJ (TM) and has been created at Xerox PARC.
Like any other aspect-oriented compiler, the AspectJ compiler includes a weaving phase that unambiguously resolves the cross-cutting between classes and aspects. AspectJ implements this additional phase by first weaving aspects with regular code and then calling the standard Java compiler. [3]
Let's consider the following example to understand this better.
source: http://www.developer.com/design/article.php/3308941/Aspect-Oriented-Programming.htm public class TestClass { public void sayHello () { System.out.println ("Hello, AOP"); } public void sayAnyThing (String s) { System.out.println (s); } public static void main (String[] args) { sayHello (); sayAnyThing ("ok"); } }
This is the existing Java code called TestClass.java. Now if we want to make use of aspects to make two modifications such as: 1.We would like to print a message before and after any call to the TestClass.sayHello() method. 2.We need to test that the argument of the TestClass.sayAnyThing() method is at least three characters.
Here is the AspectJ implementation
source: http://www.developer.com/design/article.php/3308941/Aspect-Oriented-Programming.htm 1: public aspect MyAspect { 2: public pointcut sayMethodCall (): call (public void TestClass.say*() ); 3: public pointcut sayMethodCallArg (String str): call (public void TestClass.sayAnyThing (String)) && args(str); 4: before(): sayMethodCall() { 5: System.out.println("\n TestClass." + thisJoinPointStaticPart.getSignature().getName() + "start..." ); 6: } 7: after(): sayMethodCall() { 8: System.out.println("\n TestClass." + thisJoinPointStaticPart.getSignature().getName() + " end..."); 9: } 10: before(String str): sayMethodCallArg(str) { 11: if (str .length() < 3) { 12: System.out.println ("Error: I can't say words less than 3 characters"); 13: return; 14: } 15: } 16: }
From 1, we see that an aspect is defined in the same way as a Java class. Just like any Java class, an aspect may have member variables and methods. In addition, it may include pointcuts, advices, and introductions. In lines 2 and 3, we specify the place in the TestClass code where our modification will take place. In AspectJ, 'join points' represent well-defined points in a program's execution. Typical join points in AspectJ include method/constructor calls, method/constructor execution, field get and set, exception handler execution, and static and dynamic initialization. In the example above, two join points are used :the call to TestClass.sayHello and TestClass.sayAnyThing methods. Pointcut is a language construct that picks out a set of join points based on defined criteria. The criteria can be explicit function names, or function names specified by wildcards.
public pointcut sayMethodCall (): call (public void TestClass.say*() );
In this line, we define a pointcut- sayMethodCall, which picks out any call to the TestClass.sayHello method. It also picks out any public TestClass method with zero arguments and a name that starts with 'say' (for example, TestClass.sayBye). Pointcuts are used in the definition of advice. An advice is used to define additional code to be executed before, after, or around join points. In our example, lines 4–6 and 7–9 define two advices that will be executed before and after the first pointcut. Lines 10–15 implement an advice associated with the second pointcut and are used to set a precondition before the execution of the TestClass.sayAnyThing method. Thus pointcuts and advice let us affect the dynamic execution of a program. Introduction allows aspects to modify the static structure of a program. By using introduction, aspects can add new methods and variables to a class, declare that a class implements an interface, or convert checked to unchecked exceptions.
[2]
AspectJ Plugin tool
The AspectJ Development Tools (AJDT) project provides Eclipse platform based tool with AspectJ. AspectJ is run under the same open source collective as the Eclipse project and provides the most advanced AspectJ plug-in for an IDE. The AspectJ Development Tools (AJDT) for Eclipse not only provides Eclipse users with tools to code AspectJ applications, but also includes a visualizer to show you where your aspects will be applied. To know how to install this tool AJDT, click here http://onjava.com/onjava/2004/11/24/aspect_j.pdf or http://www.eclipse.org/ajdt/EclipseCon2006/
AspectR
Aspect-oriented programming concepts to Ruby is provided by AspectR. Essentially it allows you to wrap code around existing methods in your classes. This can be a good thing (and even affect how you design your code) since it separates different concerns into different parts of the code. It is somewhat similar to AspectJ
Main features of AspectR (in AspectJ lingo):
Join points:
• Object receives method/constructor call
• Field accessed (if access is via getter/setter meth)
Advices: before (pre), after returning and after throwing (post)
Advices can access:
• Object and method receiving call
• Arguments to call
• Return value
• exceptions raised.
Aspects: classes inheriting Aspect.
Supports "abstract" Aspects and overriding between advices.
Wildcards (really regexps) can be used in pointcut designators, ie. to specify classes and methods to wrap advice's to.
Pointcut parameters.
AspectR lets a module wrap any number of methods in other classes (or objects) with the "advice" methods (in the lingo of Aspect/J) of the module.
require 'aspectr' include AspectR class MyAspect < Aspect def someAdviceMethod(method, object, exitstatus, *args) ... end ... some other advice methods ... end ma = MyAspect.new ma.wrap(someClassorObject, :preAdvice, :postAdvice, ... methods to wrap...) or ma.wrap(someClassorObject, :preAdvice, :postAdvice, /patternToWrap/) or AspectR.wrap_classes(ma, :preAdvice, :postAdvice, [Class1, Class2], ...methods to wrap...)
Advice methods are passed a variable number of parameters: the first is the name of the method currently being wrapped the second is the object receiving the method call the third is the exit/return status:
Array with return value(s) if the method exited normally true if the method exited with an exception nil if the method hasn't yet exited (for preAdvice)
the rest are the arguments that were passed to the wrapped method.
Aquarium is a framework that implements Aspect-Oriented Programming (AOP) for Ruby.
Aquarium provides a Domain Specific Language (DSL) with which you can express “aspectual” system behaviour in a modular way, i.e.,using a succinct language and without repeating yourself all over your code base!
Imagine you want to trace all invocations of the public, instance methods in all classes whose names end with “Service”. Here’s how you can implement that behavior in Aquarium:
class ServiceTracer include Aquarium::DSL before :calls_to => :all_methods, :in_types => /Service$/ do |join_point, object, *args log "Entering: #{join_point.target_type.name}##{join_point.method_name}: object = #{object}, args = #{args}" end after :calls_to => :all_methods, :in_types => /Service$/ do |join_point, object, *args|log "Leaving: #{join_point.target_type.name}##{join_point.method_name}: object = #{object}, args = #{args}" end end
The #before advice adds behavior that is invoked before each method is invoked, in this case, it logs a message with the name of the executing class and method, followed by the list of arguments passed to the method. The #after advice adds similar behavior the is invoked after each method is invoked.
A more succinct implementation of this behavior uses #around advice:
class ServiceTracer include Aquarium::DSL around :calls_to => :all_methods, :in_types => /Service$/ do |join_point, object, *args| log "Entering: {join_point.target_type.name}##{join_point.method_name}: object = #{object}, args = #{args}" result = join_point.proceed log "Leaving: #{join_point.target_type.name}##{join_point.method_name}: object = #{object}, args = #{args}" result # block needs to return the result of the "proceed"! end end
The special method #proceed invokes the advised method, passing it the args list (by default). For #around advice, you must call#proceed unless you specifically don’t want the original method called.
Appendix
1. For more information on AJDT, click here : http://eclipse.org/ajdt/
References & Resources
[1] http://onjava.com/onjava/2004/01/14/aop.html
[2] http://www.developer.com/design/article.php/3308941/Aspect-Oriented-Programming.htm
[3] http://www.voelter.de/data/articles/aop/aop.html
[4]http://rubyforge.org/projects/aquarium/