Java Aspects

Java Aspects

Class is the central unit in java like that aspect is the central unit in AspectJ. IT includes the code that defines the weaving rules for both dynamic and static crosscutting. Aspects also include data, methods, and nested class members. The below syntax defines the syntax for defining aspect.

Syntax: –

package hello.profile;
public aspect ProfilingAspect {
}

The entities of aspects are,

1)  Inter-type declarations: – This entity helps a programmer to add methods, fields or interfaces to existing classes from within the aspect.

Syntax: –

aspect VisitAspect {
void Point.acceptVisitor(Visitor v) {
v.visit(this);
}
}

2)  pointcuts: – This entity permits a programmer to specify join points. All pointcuts are expressions (quantifications) that determine whether a given join point matches.

Syntax: –

pointcut set() : execution(* set*(..) ) && this(Point);

3)  advice: – The advice entity permits a programmer to specify code to run at a join point matched by a pointcut. The actions can be performed before, after, or around the specified join point.

Syntax: –

after () : set() {
Display.update();
}

Dynamic crosscutting construct: advice:-

The dynamic cross cutting supports the advice entity. Advice is the code executed at a join point selected by a pointcut. Advice can execute before, after, or around the join point. The body of advice is much like a method body—it encapsulates the logic to be executed upon reaching a join point. The dynamic crosscutting alters the program behavior.

Eg: –

package hello.profile;
public aspect ProfilingAspect {
pointcut publicOperation() : execution(public * *.*(..));
Object around() : publicOperation() {
long start = System.nanoTime();
Object ret = proceed();
long end = System.nanoTime();
System.out.println(thisJoinPointStaticPart.getSignature()
+ “ took “ + (end-start) + “ nanoseconds”);
return ret;
}
}

Static crosscutting constructs: – The static crosscutting alters the program structure. Static crosscutting comes in the form of ,

1)      Inter-type:- The inter type declaration is a static crosscutting construct that alters the static structure of the classes, interfaces and aspects in the system.

Eg:-  We can add a method or field to a class or declare a type to implement an interface.

In an ITD one type or an aspect declares the structure for the other types like classes, interfaces and even aspects.

The below statement makes the weaver assign the AccessTracked interface as the parent of the MessageCommunicator class:

declare parents: MessageCommunicator implements AccessTracked;

When this declaration is woven in, it has the same effect as declaring the MessageCommunicator class as follows:

public class MessageCommunicator implements AccessTracked {
...
}

Another type of ITD is member introduction. It offers a way to add new methods and fields to other types. The following declaration adds the lastAccessedTime field and the

updateLastAccessedTime() and getLastAccessedTime() methods to the Access-

Tracked type:

private long AccessTracked.lastAccessedTime;
public void AccessTracked.updateLastAccessedTime() {
lastAccessedTime = System.currentTimeMillis();
}
public long AccessTracked.getLastAccessedTime() {
return lastAccessedTime;
}

This code advises all methods of types that implement the AccessTracked interface (the + wildcard denotes subtypes) but not the method in AccessTracked (such as the introduced updateLastAccessedTime() method). The this() pointcut collects the tracked object so you can call the updateLastAccessedTime() method on it.

Eg: – Tracking the last accessed time using an aspect

package hello.track;
import hello.messaging.MessageCommunicator;
public aspect TrackingAspect {
declare parents: MessageCommunicator implements AccessTracked;
private long AccessTracked.lastAccessedTime;
public void AccessTracked.updateLastAccessedTime() {
lastAccessedTime = System.currentTimeMillis();
}
public long AccessTracked.getLastAccessedTime() {
return lastAccessedTime;
}
before(AccessTracked accessTracked)
: execution(* AccessTracked+.*(..))
&& !execution(* AccessTracked.*(..))
&& this(accessTracked) {
accessTracked.updateLastAccessedTime();
}
private static interface AccessTracked {
}
}

Modified Main class to print the last-accessed time

package hello.main;
...
public class Main {
public static void main(String[] args) {
...
System.out.println(“Last accessed time for messageCommunicator “
+ messageCommunicator.getLastAccessedTime());
}
}

Weave-time declarations

This type of declaration helps to add weave-time warnings and errors when detecting certain usage patterns. Often, weaving is performed during compilation; therefore, these warnings and errors are issued when you compile the classes. Instead of SecurityAspect we can directly calls to the

Authenticator.authenticate() method. The following declaration will cause the compiler to issue a warning if any part of the system calls the prohibited method except, of course, SecurityAspect:

declare warning
call(void Authenticator.authenticate()) && !within(SecurityAspect)
“Authentication should be performed only by SecurityAspect”;

The use of the call() pointcut to select a method call (as opposed to selecting the method execution, which is always in the Authenticator class) and !within() to restrict selection of join points to only those occurring outside SecurityAspect. The weaver will report warnings when it detects the specified conditions along with other compile-time warnings such as use of a deprecated method.0

Let’s see this in action by modifying SecurityAspect to add this declaration:

package hello.security;
public aspect SecurityAspect {
...
declare warning
call(void Authenticator.authenticate())
&& !within(SecurityAspect)
“Authentication should be performed only by SecurityAspect”;
}

We can modify the main class to add new Authenticator().authenticate() to test a violation.

AspectJ alternative syntax

AOP has a lot of things in common with metalevel programming. Both capture cross-cutting aspects of a software system in clean, controlled ways. One of the most fundamental properties of metalevel programming is that the programmer has access to the structures that represent a program, i.e. a program written in a specific language is represented at runtime in this very same language. The most popular language that implements metalevel programming concepts is CLOS, the Common Lisp Object System [CLOS]. Its implementations are based on the so-called Metaobject Protocol (MOP). The MOP can be seen as a standard interface to the CLOS interpreter [MOP]. With the help of the MOP it is possible to modify the behavior of the interpreter in a controlled way. The following sections show some features of MOP in pseudo-Java syntax and show how they are related to AOP.

The alternative @AspectJ syntax extends the language using the new annotation

facility in Java 5. The advantage of using the above syntax style is that you can compile your code using a plain Java compiler

Eg: – javac

As a result, the code works better with conventional Java IDEs and tools that don’t understand the traditional AspectJ syntax. Furthermore, the proxy-based AOP framework in Spring uses this syntax, simplifying adoption of AspectJ if the project is already using Spring. The disadvantage of @AspectJ syntax is its verbosity in expressing the same constructs and its limitations in expressing certain constructs, especially in the static crosscutting category.

Eg:

package hello.security;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect                                             //  Aspect declaration
public class SecurityAspect {                 //  Aspect declaration
private Authenticator authenticator = new Authenticator();
@Pointcut(
“execution(* hello.messaging.MessageCommunicator.deliver(..))”)      //  Pointcut declaration.
public void secureAccess() {}
@Before(“secureAccess()”)                  //    Advice
public void secure() {                              //    Advice
System.out.println(“Checking and authenticating user”);                //    Advice
authenticator.authenticate();
}
}