Java and Spring development

@AspectJ cheat sheet

with 10 comments

This cheat sheet uses AspectJ’s @AspectJ style. It’s also possible to use the original AspectJ syntax like this example demonstrates, but I prefer to use standard Java classes with the AspectJ logic inside annotations.

Pointcuts

The definition of a pointcut from the AspectJ homepage:

A pointcut is a program element that picks out join points and exposes data from the execution context of those join points. Pointcuts are used primarily by advice. They can be composed with boolean operators to build up other pointcuts.

A pointcut example:

Pointcut designators

A method pointcut:

@Pointcut("[method designator](* aspects.trace.demo.*.*(..))")
public void traceMethodsInDemoPackage() {}
  • call – The pointcut will find all methods that calls a method in the demo package.
  • execution – The pointcut will find all methods in the demo package.
  • withincode – All the statements inside the methods in the demo package.

A type pointcut:

@Pointcut("[type designator](*..*Test)")
public void inTestClass() {}
  • within – all statements inside the a class that ends with Test.

A field pointcut:

@Pointcut("[field designator](private org.springframework.jdbc.core.JdbcTemplate " +
       "integration.db.*.jdbcTemplate)")
public void jdbcTemplateGetField() {}
  • get – all reads to jdbcTemplate fields of type JdbcTemplate in the integration.db package. Includes all methods on this field if it’s an object.
  • set – when you set the jdbcTemplate field of type JdbcTemplate in the integration.db package to a new value.

Signature pointcuts

This chapter explains more advanced signature pointcuts than illustrated on the image above.

Support for sub packages is provided with “..”:

@Pointcut("within(*..*Test)")
public void inTestClass() {}

To find the joinpoints inside a type that ends with Test inside the ..demo package:

@Pointcut("within(com.redpill.linpro.demo..*Test)")
public void inDemoProjectTestClass() {}

All statements inside all classes except test classes in the ..demo package with the “!” before the designator:

@Pointcut("!within(com.redpill.linpro.demo..*Test)")
public void notInDemoProjectTestClass() {}

All methods in the Service class or a subtype of it:

@Pointcut("execution(void *..service.Service+.*(..))")
public void servicePointcut() {}

All getCoffeeType methods in a class that begins with CoffeeTypeRepository:

@Pointcut("execution(CoffeeType integration.db.CoffeeTypeRepository*.getCoffeeType(CoffeeTypeName))" +
    " && args(coffeeTypeName)")
public void getCoffeeTypePointcut(CoffeeTypeName coffeeTypeName) {}

Note that the pointcut also contains args(coffeeTypeName) and that the Java method has a method with a CoffeeTypeName as input parameter. An advice that advices this pointcut must also have this input parameter.

This field pointcut finds all the places in the integration package where a field named jdbcTemplate gets a new value of type JdbcOperations or a subtype of it like JdbTemplate.

@Pointcut("set(private org.springframework.jdbc.core.JdbcOperations+ " +
    "integration..*.jdbcTemplate)")
public void jdbcTemplateSetField() {}

Annotation pointcuts

A pointcut can declare an annotation before the signature pattern.

An example of an annotation used as a marker interface:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PerformanceLogable {}

All it does is to provide meta information to methods.

A pointcut that finds all methods marked with the @PerformanceLogable on the classpath:

@Pointcut("execution(@aspects.log.performance.PerformanceLogable * *(..))")
public void performanceLogableMethod() {}

The @Transactional annotation supports both method and type target. Which means it can be used with both method and type designators. The pointcut below is the same as the performanceLogableMethod pointcut, except it finds methods with Spring’s @Transactional annotation.

@Pointcut("execution(@org.springframework.transaction.annotation.Transactional * *(..))")
public void transactionalMethod() {}

A pointcut that finds all constructors marked with @Inject and have an integer as input parameter:

@Pointcut("execution(@javax.inject.Inject *.new(Integer)) && args(integer)")
public void constructorAnnotatedWithInjectAndIndemoPackage(Integer integer) {}

The @Service annotation has target set to type and can therefore only annotate types. The pointcut below will find all statements in all types marked with @Service.

@Pointcut("within(@org.springframework.stereotype.Service *)")
public void serviceBean() {}

The joinpoint will be all statements inside a type marked with the @Component annotation or a specialization of it:

@Pointcut("within(@(@org.springframework.stereotype.Component *) *)")
public void beanAnnotatedWithComponentOrASpecializationOfIt() {}

Finds all statements that’s not inside a method marked with @Test:

@Pointcut("!withincode(@org.junit.Test * *(..))")
public void notInTestMethod() {}

Finds all methods with one or more parameters marked with the @MyParamAnnotation:

@Pointcut("execution(public * *(.., @aspects.MyParamAnnotation (*), ..))")
public void methodWithAnnotationOnAtLeastOneParameter() {}

For a full example with explanations, see this post.

A pointcut with a runtime condition and a required public static method:

@Pointcut("execution(* *.actionPerformed(java.awt.event.ActionEvent)) " +
		"&& args(actionEvent) && if()")
public static boolean button1Pointcut(ActionEvent actionEvent) {
	return (actionEvent.getSource() == j1);
}

More information can be found in this post

Combining pointcuts

Instead of having a large pointcut, it’s a much better approach to combine several pointcuts into one.

@Pointcut("traceMethodsInDemoPackage() && notInTestClass() && notSetMethodsInTraceDemoPackage()")
public void filteredTraceMethodsInDemoPackage() {}

Advices

The definition from the AspectJ homepage:

A piece of advice brings together a pointcut and a body of code to define aspect implementation that runs at join points picked out by the pointcut.

An advice can be executed before, after, after returning, after throwing or around the joinpoint.

The before advice below is executed before the target method specified in filteredTraceMethodsInDemoPackage pointcut:

@Before("filteredTraceMethodsInDemoPackage()")
public void beforeTraceMethods(JoinPoint joinPoint) {
	// trace logic ..
}

This after advice is executed after the target method.

@After("filteredTraceMethodsInDemoPackage()")
public void afterTraceMethods(JoinPoint joinPoint) {
	// trace logic ..
}

The afterThrowing advice will be executed if the method that matches the pointcut throws an exception. You can also declare the Exception and handle it like this:

@AfterThrowing(value="serviceMethodAfterExpcetionFromIntegrationLayerPointcut()", throwing="e")
public void serviceMethodAfterExceptionFromIntegrationLayer(JoinPoint joinPoint,
                RuntimeException e) {
	StringBuilder arguments = generateArgumentsString(joinPoint.getArgs());

	logger.error("Error in service " + joinPoint.getSignature() + " with the arguments: " +
			arguments, e);
}

The AfterReturning advice will only be executed if the adviced method returns successfully.

@AfterReturning("transactionalMethod()")
public void afterTransactionalMethod(JoinPoint joinPoint) {
	transactionService.commit();
}

The around advice is quite powerful, but also consumes more resources and should only be used if you can’t make it work with other advices. The example below simulates some logic before and after the adviced method. The ProceedingJoinPoint extends the JoinPoint class and is required to call the adviced method with the proceed() method.

@Around("performanceLogablePointcut()")
public void aroundPerformanceLogableMethod(ProceedingJoinPoint point) {

    // Pre processing work..

    point.proceed();

    // Post processing work..
}

Note: You don’t need an around advice to monitor the execution time for a method. It’s just the simplest option and therefore used in this example.

The advice below combines two pointcuts and the last one has an integer object as input parameter. This requires the Java method to also have an integer parameter. It enables the advice logic to access the input parameter directly and in a type safe manner. A less elegant alternative is to access the parameter with the joinPoint’s getArgs() method.

@AfterReturning("beanAnnotatedWithComponentOrASpecializationOfIt() &&  " +
	"constructorAnnotatedWithInjectAndIndemoPackage(integer)")
public void afterReturningFromConstructorInSpringBeanWithIntegerParameter(
		JoinPoint joinPoint, Integer integer) {

	// Advice logic..
}

Summary

This cheat sheet consist of many simple pointcuts. Often you have to combine them to add value to your application. This example article combines pointcuts with a class marked with @Service and a constructor and method marked with @Inject. It also filters away the test method with the @Test annotation.

The code used in this article was developed in my work time at Redpill Linpro.


Redpill Linpro is the leading provider of Professional Open Source services and products in the Nordic region.

About these ads

Written by Espen

March 20, 2010 at 18:28

Posted in Aspects

Tagged with , , ,

10 Responses

Subscribe to comments with RSS.

  1. Hi very good work, thank you a lot :)

    Boehm

    July 16, 2010 at 18:07

  2. Hi,

    Thanks for this sheet … was very usefull for me =)

    Marcio Barroso

    April 27, 2011 at 18:35

  3. [...] The “&&” is no error, it’s just && condition escaped in xml. If you do not understand aspectj pointcut definition syntaxt, here is a little cheat sheet. [...]

  4. You are awesome!! Thanks a lot!! Very usefull!!

    Anonymous

    November 7, 2012 at 11:45

  5. Superb ! you covered many examples in one blog !

    Anonymous

    April 25, 2013 at 00:33

  6. […] 这个部分参看这篇 blog。这里摘选部分: […]

  7. What version of Spring are you using? I’m trying to do something like this:
    @Pointcut(“execution(* *.actionPerformed(java.awt.event.ActionEvent)) ” +
    “&& args(actionEvent) && if()”)

    but it seems that the ‘if()’ is not supported by Spring. Im using 3.1.1.RELEASE and aspectj 1.0.7

    Anonymous

    November 18, 2013 at 18:48

    • I don’t use Spring on these examples.

      You need to use AspectJ with compile-time or load-time weaving. Spring AOP runtime-weaving doesn’t support all the functionality demonstrated in this cheat sheet.

      Espen

      November 21, 2013 at 09:14

  8. […] An excellent cheat sheet […]

  9. […] AspectJ Cheat Sheet. […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 37 other followers

%d bloggers like this: