public aspect MyAspect { }
(aop for friends)
Aspect-oriented programming is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns.
It does so by adding additional behavior to existing code without modifying the code itself.
Caching
Logging
Monitoring
Transaction processing
AspectJ (Java)
PostSharp (.NET)
AspectCobol
…
Compile-Time Weaving
Post-Compile Weaving
Load-Time Weaving
public aspect MyAspect { }
execution(void Point.setX(int)) // method body executed
call(void Point.setX(int)) // method is called
handler(ArrayOutOfBoundsException) // exception handler
within(MyClass) // executing code belongs to class MyClass
this, target, cflow, setter...
before(): myPointcut() {startTimer();}
after(): myPointcut() {stopTimer();}
around(): myPointcut() {return proceed();}
Single Pointcut
after: myPointcut() {}
Joint Pointcuts
after: myPointcut() || otherPointcut() {}
Inline Pointcut
after: myPointcut() && otherPointcut() {}
Parameterized Pointcut
after(String s): myPointcut(s) {}
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj}</version>
</dependency>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>${aspectj-plugin}</version>
</plugin>
// Pony.java
package bzh.zomzog.prez.aop;
public class Pony {
private int distance = 0;
public boolean makeItWalk(int distance){
this.distance += distance;
return true;
}
public int getDistance() {
return distance;
}
}
// PonyAspect.aj
package bzh.zomzog.prez.aop;
public aspect PonyAspect {
pointcut callMakeItWalk(int distance, Pony pony) :
call(boolean Pony.makeItWalk(int))
&& args(distance)
&& target(pony);
}
before(int distance, Pony pony) : callMakeItWalk(distance, pony) {
if (distance > 10) {
throw new RuntimeException("Too long for a pony");
}
}
after(int distance, Pony pony) : callMakeItWalk(distance, pony) {
System.out.println("After " + pony);
}
boolean around(int distance, Pony pony)
: callMakeItWalk(distance, pony) {
long startTime = System.nanoTime();
boolean result = proceed(distance, pony);
long endTime = System.nanoTime();
System.out.println("Duration : " + (endTime-startTime));
return result;
}
@Aspect
public class MyAspect { }
@Pointcut("execution( ... )")
public void myExecutionPointcut() { }
@Pointcut("@within( AnotherAnnotation )")
public void myWithinAnnotationPointcut() { }
@Before("myExecutionPointcut()")
@After("myWithinAnnotationPointcut()")
@Around("execution( ... )")
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj}</version>
</dependency>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>${aspectj-plugin}</version>
</plugin>
// Pony.java
package bzh.zomzog.prez.aop;
public abstract class Pony {
private int distance = 0;
public boolean makeItWalk(int distance){
this.distance += distance;
return true;
}
public int getDistance() {
return distance;
}
}
// Unicorn.java
@Slow
public class Unicorn extends Pony { }
// Pegasus.java
public class Pegasus extends Pony { }
// PonyAspect.java
package bzh.zomzog.prez.aop;
@Aspect
public class PonyAspect {
@Pointcut("execution(* bzh.zomzog.prez.aop.domain.Pony.makeItWalk(..))")
public void callMakeItWalk() { }
@Pointcut("@within(bzh.zomzog.prez.aop.Slow)")
public void slowAnnotation() { }
}
@Before("slowAnnotation()")
public void beforeAnnotation(JoinPoint joinPoint) {
System.out.println("Annotation : " + joinPoint);
}
@Before("callMakeItWalk()")
public void beforeExecution(JoinPoint joinPoint) {
System.out.println("Excecution : " + joinPoint);
}
@Before("callMakeItWalk() && slowAnnotation()")
public void slow(JoinPoint joinPoint) {
System.out.println("E&&A : " + joinPoint);
int distance = (Integer) joinPoint.getArgs()[0];
if (distance > 10) {
throw new RuntimeException("Distance is too long for a pony");
}
}
// new Pegasus().makeItWalk(100);
Excecution : execution(boolean Pony.makeItWalk(int))
// new Unicorn().makeItWalk(100);
Annotation : staticinitialization(Unicorn.<clinit>)
Annotation : preinitialization(Unicorn(String))
Annotation : initialization(Unicorn(String))
Annotation : execution(Unicorn(String))
Annotation : execution(boolean Unicorn.makeItWalk(int))
Excecution : execution(boolean Unicorn.makeItWalk(int))
E&&A : execution(boolean Unicorn.makeItWalk(int))
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Configuration
@EnableAspectJAutoProxy
public class AopConfiguration {
@Bean
@Profile("verbose")
public LoggingAspect loggingAspect() {
return new LoggingAspect();
}
}
Source code and slide can be found on https://github.com/Zomzog/aop