I will provide a stand-alone AspectJ solution, but in spring AOP it would the same way, only the aspect and your target classes need to be Spring beans/components, so don't forget annotations like @Component
, as shown by Ian Mc.
Helper class + interface + implementations:
package de.scrum_master.app;
public class A {
private String name;
public A(String name) {
this.name = name;
}
@Override
public String toString() {
return "A [name=" + name + "]";
}
}
package de.scrum_master.app;
public interface MyInterface {
public A doSomething();
}
package de.scrum_master.app;
public class FirstImpl implements MyInterface {
@Override
public A doSomething() {
return new A("First");
}
}
package de.scrum_master.app;
public class SecondImpl implements MyInterface {
@Override
public A doSomething() {
return new A("Second");
}
}
Driver application:
package de.scrum_master.app;
public class Application {
private static MyInterface myInterface;
public static void main(String[] args) {
myInterface = new FirstImpl();
for (int i = 0; i < 5; i++) {
System.out.println(myInterface.doSomething());
}
myInterface = new SecondImpl();
for (int i = 0; i < 5; i++) {
System.out.println(myInterface.doSomething());
}
}
}
Console log without aspect:
A [name=First]
A [name=First]
A [name=First]
A [name=First]
A [name=First]
A [name=Second]
A [name=Second]
A [name=Second]
A [name=Second]
A [name=Second]
So far, so boring.
Aspect:
Now let us implement a stupid little aspect randomly deciding about method execution vs. skipping and providing another return value instead (because I do not know the real condition which would cause you to skip method execution):
package de.scrum_master.aspect;
import java.util.Random;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.A;
@Aspect
public class MyAspect {
private static Random random = new Random();
@Around("execution(A de.scrum_master.app.MyInterface.*(..))")
public A interceptCalls(ProceedingJoinPoint thisJoinPoint) throws Throwable {
if (random.nextBoolean())
return (A) thisJoinPoint.proceed();
else
return new A("Aspect");
}
}
Console log with active aspect:
A [name=Aspect]
A [name=First]
A [name=Aspect]
A [name=Aspect]
A [name=First]
A [name=Aspect]
A [name=Second]
A [name=Second]
A [name=Aspect]
A [name=Second]