You want to use @Around advice from AspectJ and do something like this:
// Let subClass instances run normally... cec.setActive(true); letThemDoSomething("BEFORE", sbc1, sbc2, sbc3); // Now change existing scenario... cec.setActive(false); letThemDoSomething("AFTER", sbc1, sbc2, sbc3);
This will output:
BEFORE ====== SubClass1: doSomething() called. SubClass2: doSomething() called. SubClass3: doSomething() called. AFTER ====== Blocking instance<1> method: my.first.spring.aop.aspectj.SubClassN
In the following lines I will describe how to do this with annotation.
I will also use Spring here. This helps make the configuration faster and easier.
1- Configuration
Tools and Dependencies
Java 7, AspectJ 1.7.4, Spring 4.0.2
Project structure

pom.xml
<project ...> <properties> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <spring.version>4.0.2.RELEASE</spring.version> <aspectj.version>1.7.4</aspectj.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> </project>
2 - Existing code
Baseclass.java
public class BaseClass { public void doSomething() { } public void say(String msg) { System.out.println(msg); } }
SubClassN.java
public class SubClassN extends BaseClass { private Integer index; public SubClassN(Integer index) { this.index = index; } @Override public void doSomething() { say("SubClass" + index + ": doSomething() called."); } public Integer getIndex() { return index; } }
3 - Modify existing code (without breaking anything ...)
Here comes AspectJ and his @Around tips. First, we will ask AsjectJ to call a specific method when the doSomething method is doSomething . doSomething can be anywhere in BaseClass or in any of its child classes.
This particular method is called changeExistingScenario . It can have any name. Important here is the annotation posted on it.
A word about the meaning of @Around:
Execution (* my.first.spring.aop.aspectj.BaseClass.doSomething (..))
This expression simply indicates the signature template of the method we want to intercept.
It will intercept any doSomething method in the BaseClass or child class, regardless of how many parameters, return type and access modifier.
For more details see: http://guptavikas.wordpress.com/2010/04/15/aspectj-pointcut-expressions/
ChangeExistingCode.java
@Aspect // Mark ChangeExistingCode as the class for modifying the code @Component public class ChangeExistingCode { private boolean active; public void setActive(boolean active) { this.active = active; } /** * * This method will be called by AspectJ anytime a `doSomething` method is called. * * This will give us a chance to decide whether the `doSomething` method should * be called or not. * */ @Around("execution(* my.first.spring.aop.aspectj.BaseClass.doSomething(..))") public void changeExistingScenario(ProceedingJoinPoint joinPoint) throws Throwable { // Is active ? if (active) { // Yes, let doSomething() run as usual joinPoint.proceed(); } else {// No, block doSomething() invokation Signature s = joinPoint.getSignature(); System.out.format( // "Blocking instance<%d> method: %s#%s(%s) !!\n", // ((SubClassN)joinPoint.getTarget()).getIndex(), // s.getDeclaringTypeName(), // s.getName(), // Arrays.toString(joinPoint.getArgs()) // ); } } }
4- Let all the magic appear ...
Main.java
@Configuration // Mark the Main class as the class where Spring will find its configuration @ComponentScan // Ask Spring to look for other components within the Main class package @EnableAspectJAutoProxy // Let Spring auto configure AspectJ aspects for us... public class Main { private static int subClassCounter; public static void main(String[] args) { subClassCounter=0; GenericApplicationContext context = new AnnotationConfigApplicationContext(Main.class); SubClassN sbc1 = context.getBean(SubClassN.class); SubClassN sbc2 = context.getBean(SubClassN.class); SubClassN sbc3 = context.getBean(SubClassN.class); ChangeExistingCode cec = context.getBean(ChangeExistingCode.class); // Let subClass instances run normally... cec.setActive(true); letThemDoSomething("BEFORE", sbc1, sbc2, sbc3); // Now change existing scenario... cec.setActive(false); letThemDoSomething("AFTER", sbc1, sbc2, sbc3); context.close(); } private static void letThemDoSomething(String prefix, SubClassN... existingClasses) { System.out.format("%s ======\n", prefix); for (SubClassN subClassInstance : existingClasses) { subClassInstance.doSomething(); } System.out.println(); } @Bean // Tell Spring to use this method for creating SubClassN instances @Scope(BeanDefinition.SCOPE_PROTOTYPE) // Scope prototype force creation of multiple instances private static SubClassN buildSubClassN() { subClassCounter++; return new SubClassN(subClassCounter); } }
Output
BEFORE ====== SubClass1: doSomething() called. SubClass2: doSomething() called. SubClass3: doSomething() called. AFTER ====== Blocking instance<1> method: my.first.spring.aop.aspectj.SubClassN
5 Links