uncle bob
uncle bob

Reputation: 680

How to define pointcut for class initialization

I'm a newbie to AspectJ, and trying to understand joinpoint model Now i have class like this

public class Account {
 private static Map<String, PaymentMethod> supportedPayments = new HashMap<>();
 static {
   supportedPayments.add("COD", new CodPaymentMethod());
   supportedPayments.add("ATM", new ATMPaymentMethod());
 }
}

as i read from AspectJ In Action, there is a way to define pointcut when class is intialization, but i could not find syntax. Anyone help me?

This one does not work:

@Pointcut("initialization(com.jas.aop.bean.Payment"))

it say

ERROR] Syntax error on token "initialization(com.jas.aop.bean.Payment)", "name pattern" expected
/Users/admin/eclipse-workspace/aop/src/main/java/com/jas/aop/aspect/ClassInitializationAspect.java:9
@Pointcut("initialization(com.jas.aop.bean.Payment)")

Upvotes: 0

Views: 992

Answers (1)

kriegaex
kriegaex

Reputation: 67297

Your pointcut has several problems:

  • There is a missing closing parenthesis ).
  • initialization intercepts constructors (i.e. object initialisation) rather than static class initialisation, which is not what you want and also would require a constructor pattern, not a class name pattern.
  • If your aspect does not happen to be in the exact same package as the target class, you must use a fully qualified class name such as my.package.Account in order to make the pointcut match.

By the way, your code snippets are just pseudo code because a hash map does not have an add method, rather a put method. The sample class does not even compile. Don't just invent code when posting questions here. Make life easier for the people trying to help you.

Now here is an MCVE, something I always suggest you to specify in your question in order to help people reproduce your situation. I did it for you this time, this was your free shot. Next time, please do it yourself.

Dependency classes used by the main class:

package de.scrum_master.app;

public interface PaymentMethod {}
package de.scrum_master.app;

public class ATMPaymentMethod implements PaymentMethod {}
package de.scrum_master.app;

public class CodPaymentMethod implements PaymentMethod {}

Target class with driver application:

package de.scrum_master.app;

import java.util.HashMap;
import java.util.Map;

public class Account {
  private static Map<String, PaymentMethod> supportedPayments = new HashMap<>();

  static {
    System.out.println("Static initialiser block");
    supportedPayments.put("COD", new CodPaymentMethod());
    supportedPayments.put("ATM", new ATMPaymentMethod());
  }

  public Account() {
    System.out.println("Creating account");
  }

  public void doSomething() {
    System.out.println("Doing something");
  }

  public static void main(String[] args) {
    new Account().doSomething();
  }
}

Aspect:

The aspect shows both initialization and staticinitialization in order to show the difference in both syntax and functionality. You can find all of this explained with examples in the AspectJ manual, which I warmly recommend you to read.

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AccountAspect {
  @Before("initialization(de.scrum_master.app.Account.new(..))")
  public void interceptObjectInitialisation(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }

  @Before("staticinitialization(de.scrum_master.app.Account)")
  public void interceptClassInitialisation(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }
}

Console log:

staticinitialization(de.scrum_master.app.Account.<clinit>)
Static initialiser block
initialization(de.scrum_master.app.Account())
Creating account
Doing something

Upvotes: 1

Related Questions