Aspect Oriented Programming

(aop for friends)

Wikipedia

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.

Cross-cutting Examples

  • Caching

  • Logging

  • Monitoring

  • Transaction processing

Who can use it ? Nearly everybody

  • AspectJ (Java)

  • PostSharp (.NET)

  • AspectCobol

  • …​

When ?

  • Compile-Time Weaving

  • Post-Compile Weaving

  • Load-Time Weaving

Aspect class .aj

    public aspect MyAspect { }

Pointcut

    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...

Advice

before(): myPointcut() {startTimer();}

 

after(): myPointcut() {stopTimer();}

 

around(): myPointcut() {return proceed();}

Pointcut logical

Single Pointcut

    after: myPointcut() {}

Joint Pointcuts

    after: myPointcut() || otherPointcut() {}

Inline Pointcut

    after: myPointcut() && otherPointcut() {}

Parameterized Pointcut

    after(String s): myPointcut(s) {}

Demo .aj

<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;
}

AspectJ with Java-5

AspectJ with java 5

    @Aspect
    public class MyAspect { }

Pointcut with java 5

    @Pointcut("execution( ... )")
    public void myExecutionPointcut() { }
    @Pointcut("@within( AnotherAnnotation )")
    public void myWithinAnnotationPointcut() { }

Advice with java 5

    @Before("myExecutionPointcut()")
    @After("myWithinAnnotationPointcut()")
    @Around("execution( ... )")

Demo java-5

<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))

Spring AOP

        <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();
    }
}

Questions

Thanks

Source code and slide can be found on https://github.com/Zomzog/aop