Defining Custom AspectJ Annotations

One of my recent work challenges was to define a custom annotation eligible for Spring autowired dependency injection using Aspect-Oriented Programming (AOP), so I’m my findings describing here.

The following components are required to define a custom AspectJ annotation based interceptor, within a web application.

Annotation definitions

To define a custom annotation, define an @interface decorated with the following:

@Target – Indicates the contexts in which an annotation type is applicable
@Retention – Describes how long the annotations with the annotated type will be retained

Example:

@Target(value = METHOD)
@Retention(value = RUNTIME)
public @interface AuthHeadersExtractor {
}

Define the Aspect

The aspect class should be @Aspect annotated, to mark it as an aspect declaration. It should also be registered with the @Component annotation, thus making it eligible for receiving injections of other managed beans via the @Autowire annotation.

Example:

@Aspect
@Component
public class AuthHeadersAspect {
@Autowired
AuthHeaders authHeaders;

@Before(“execution(public void com.rakkatak.example..get*(userId, token))”)
public void extractAuthHeaders(String userId, String token){
authHeaders.setUserId(userId);
authHeaders.setToken(token);
}
}

Please refer to the following for more information on AOP concepts and advice types such as @Before:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

Aspect configuration

The aop.xml file is standard AspectJ convention. It should be placed on the class path and will inform the AspectJ weaver that we want to weave our Profiling Aspect into our classes.

Example:
<!DOCTYPE aspectj PUBLIC “-//AspectJ//DTD//EN” “http://www.eclipse.org/aspectj/dtd/aspectj.dtd”>
<aspectj>
<weaver>
<!– only weave classes in this package –>
<include within=” com.rakkatak.example.*” />
</weaver>
<aspects>
<!– use only this aspect for weaving –>
<aspect name=” com.rakkatak.example.aspects.AuthHeadersAspect” />
</aspects>
</aspectj>

Initializing the Aspect

Because the @Aspect annotated class is registered using the @Component annotation, additional configuration is required to initialize the aspect. This configuration can occur in a @Configuration file.

Example:

@Configuration
public class WebAppConfig {

@Bean
public AuthHeadersAspect authHeadersAspect() {
AuthHeadersAspect aspect = Aspects.aspectOf(AuthHeadersAspect.class);
return aspect;
}
}

The static “Aspects.aspectOf” method will grab the instance of the aspect that AspectJ made when it found the aspect’s class via the element in aop.xml. Returning this instance within a method annotated with @Bean in a component scanned class annotated with @Configuration will pass that aspect instance to Spring to become a managed bean, making it eligible for @Autowired dependency injection.

Use the Aspect

Finally use your annotation on a method.

Example:

@RestController
public class SampleController {

@RequestMapping(“/accountList”)
@AuthHeadersExtractor
public Greeting greeting(@RequestHeader(value=”userId”) String userId, @RequestHeader(value=”token”) String token) {
return sampleService.getList();
}
}

Leave a Reply

Your email address will not be published.