280 likes | 421 Views
Overview of AspectJ. Aspect Oriented Software Development Seminar Technion presented by Oren Mishali. Aspect Oriented Programming A reminder …. During the life cycle of a software system, we are encountered with crosscutting concerns that span multiple modules. e.g. tracing, caching ….
E N D
Overview of AspectJ Aspect Oriented Software Development Seminar Technion presented by Oren Mishali
Aspect Oriented ProgrammingA reminder… • During the life cycle of a software system, we are encountered with crosscutting concerns that span multiple modules. • e.g. tracing, caching … • Attempt to implement them in a traditional way (OOP) leads to scattering & tangling. • AOP suggests the separation of each concern into unit of modularization –aspect.
Our simple banking system Client * Clerk << uses >> * Account - balance:float +deposit(float) +withdraw(float) • While developing , we want to trace each public method call. • Solution without AspectJ: • Look for public mehod calls and insert printing before the call.
AspectJ solution PublicTracing.java aspect PublicTracing { pointcut publicCalls() : call ( public *.* (..) ); before() : publicCalls() { System.out.println(“Calling public method”); } } • ajc *.java • java BankingSystem Calling public method Calling public method …………………
AspectJ • General-purpose, aspect oriented extension to java. • Every valid java program is also a valid AspectJ program. • With AspectJ: • You implement the core concerns using java. • You use the extensions provided to implement the aspects. • You weave them together with ajc (no need for javac). • May 25, 2004 - AspectJ 1.2 released.
Dynamic crosscuting • AspectJ enables us to define events in the program flow and then add an advice at those events. • This capability is called dynamic crosscutting • Keywords: join point, pointcut, advice. • Is it possible to add an advice before the execution of a while block ? • Or before the execution of a method?
Join points • Join point is an event in the execution of a program. • With well defined start point and end point. e.g. execution of a for block, method call, static initialization of a class, execution of a catch block … • Exposed join points are subset of all possible join points that AspectJ exposes to us. • In practice it means that we can only add advice at exposed join points. • So what are they?
Exposed join points in AspectJMethod call & Method execution acount.deposit(amount) :Client account:Account deposit(amount) deposit execution deposit call • The most useful join points. • For most purposes, the difference does not matter. • What is the difference?
Exposed join points in AspectJAll the rest… • Constructor call & execution • Field read & write access ( Except for local or const ) • Execution of a catch block • Static initialization of a class • Object initialization & pre-initialization • Execution of an advice ( Advise an advice ? ) Is it possible to add an advice before the execution of a while block ?
Pointcuts • Join point is a concept. • Pointcut is a syntactic construct that define a set of join points. • Suppose we want to trace each execution of a catch block that handles exception of type AccountException: before() : handler(AccountException) { System.out.println(“Before execution of catch block”); } • Or: pointcutaccountExceptionHandler(): handler(AccountException); before() : accountExceptionHandler() { System.out.println(“Before execution of catch block”); } Anonymous pointcut Named pointcut
Pointcuts (cont.) • In same manner, a pointcut syntax exists for each kind of a join point. • E.g. call( pattern ), execution( pattern ), set( pattern ) … • Use * , + , .. wildcards to define a common pattern. • Use operators to create complex pointcuts: • !p- each join point that is not defined by pointcut p. • p1||p2–each join point that is defined by either p1 or p2. • p1&&p2–each join point that is defined by bothp1 and p2. • E.g. set(private float Account.balance) && get(private float Account.balance) set(private float Account.balance) || get(private float Account.balance)
More primitive pointcuts… • Some join points have arguments: • Method and constructor join points. • Execution of a catch block ( handled exception ). • Field write access ( new value to be set ). • Suppose we want to trace each join point that has one argument of type String. • We can do that using args( pattern ) primitive pointcut: before() : args( String ) { System.out.println( “Before one String parameter”); }
More primitive pointcuts… • Suppose we want to trace each call to Account.deposit(float) made by a Clerk objectbut not by a Client object. • call( public void Account.deposit(float) ) ? • this( Type ) pointcut defines all join points where this-object is subtype of Type including Type itself. before() : call( public void Account.deposit(float) ) && this ( Clerk ) { System.out.println( “Clerk object calls Account.deposit()” ); } • target( Type ) is similar but based on the target object. call( * Account+.*(..) ) ==target( Account ) ?
Passing context from join point to advice • Advice often needs some information about the advised join point. (context) • E.g. advice on a method call join point wants to print the caller object (this), the called object (target), or the method arguments. • A pointcut may exposes arguments/this-object/target-object from a join point. pointcut withdrawOperations(Client client, Account account, float amount) : call( public void Acount.withdraw( float ) ) && this( client ) && target( account ) && args( amount ) ;
Advicebefore() advice • Logic - permit withdraw only if Acount.balance >= amount. before( Client client, Account account, float amount ) throws AccountException : withdrawOperations( client, account, amount ) { if ( account.balance() < amount ) { client.send(“Please contact you bank office”); account.block(true); throw new AccountException(); } }
Advicearound() advice • Logic – if amount > Account.balance, withdraw balance. void around( Client client, Account account, float amount ) throws AccountException: withdrawOperations( client, account, amount) { if ( amount < account.balance() ) proceed( client, account, amount); else proceed( client, account, account.balance() ); } • around() advice executes instead of the join point. • You must specify a return value.
Adviceafter() advice • Several kinds of after() advice: • after returning()– executes only after a successful return. • after throwing()– executes only after thrown exception. • after()– executes after both cases. • We can access the return value / exception : after() returning(float amount) : call( Account.balance(..) ) { Logger.log(amount); }
Aspect • Is the basic unit of modularization for crosscutting concern in AspectJ. • Can includes advice, pointcuts, introductions and compile-time declarations. • An aspect is like a class: • Can include data members and methods. • Can have access specifier. • Can be declared as abstract. • Can be embedded inside classes and interfaces. • An aspect is not a class: • Cannot be directly instantiated with new. • Instantiation is done by the system. Singleton by default. • Cannot inherit from concrete aspects. • Can have a privileged access specifier. • Gives it access to the private member of the class it is crosscutting.
Static crosscutting • Is modifying the static structure of the program or its compile-time behavior. • Member introduction. • Adding classes fields or methods. • Type-hierarchy modification. • Adding classes interfaces or a super class. • Compile-time errors and warnings. • Based on certain usage pattern.
Static crosscuttingMember introduction • Suppose we want to allow deposit only if it is higher than last deposit. • We need lastDeposit field. Where? aspect DepositAspect { private float Account.lastDeposit = 0;// private to the aspect, not to Account. void around( Account account, float amount ) : execution ( void Account.deposit(float) ) && args( amount ) &&this(account) { if ( amount > account.lastDeposit ) { proceed( account, amount ); account.lastDeposit = amount; } } }
More on AspectJ:cflow() and cflowbelow() pointcuts Account.withdraw( amount ) • The program fails in the marked area. • should we trace using execution(Database.confirm(float)) ? • cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. • cflowbelow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. :Client :Account :Database withdraw(amount) confirm(amount)
More on AspectJ:clflow() & cflowbelow() pointcuts Account.withdraw( amount ) • The program fails in the marked area. • should we trace using execution(Database.confirm(float)) ? • cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. • cflowbelow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. :Client :Account :Database withdraw(amount) confirm(amount) • cflow( call(Account.withdraw(float)) && this(Client) )
More on AspectJ:clflow() & cflowbelow() pointcuts Account.withdraw( amount ) • The program fails in the marked area. • should we trace using execution(Database.confirm(float)) ? • cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. • cflowbelow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. :Client :Account :Database withdraw(amount) confirm(amount) • cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) )
More on AspectJ: clflow() & cflowbelow() pointcuts Account.withdraw( amount ) • The program fails in the marked area. • should we trace using execution(Database.confirm(float)) ? • cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. • cflowbelow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. :Client :Account :Database withdraw(amount) confirm(amount) • cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) ) • cflowbelow( call(Account.withdraw(float)) && this(Client) )
More on AspectJ clflow() & cflowbelow() pointcuts Account.withdraw( amount ) • The program fails in the marked area. • should we trace using execution(Database.confirm(float)) ? • cflow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut including the pointcut join points. • cflowbelow( pointcut ) Defines all join points that occur in the flow of the join points defined by pointcut excluding the pointcut join points. :Client :Account :Database withdraw(amount) confirm(amount) • cflow( call(Account.withdraw(float)) && this(Client) ) && execution( Database.confirm(float) ) • cflowbelow( call(Account.withdraw(float)) && this(Client) ) && execution(Database.confirm(float))
More on AspectJthisJoinPoint • Special reference variable that contains static and dynamic information of a join point. • May be used by an advice. • Usage involves run-time creation overhead. • Use thisJoinPointStaticPart when only static information is necessary. • When possible, prefer usage of args() this() and target() to collect dynamic information.
More on AspectJAdvice precedence • Often, several advices may advise the same join point in the same place. • What is the order of execution? • Precedence of such advices in a single aspect is according to their lexical appearance. • declare precedence construct should be used when order of execution is important among different aspects. • declare precedence : FirstAspect , SecondAspect; specifies that advices of FirstAspect take higher precedence.