• Stars
    star
    164
  • Rank 230,032 (Top 5 %)
  • Language
    Java
  • Created almost 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Sample applications showing how to use AspectJ with Spring Boot

Sample Apps Showing How to Use AspectJ Natively with @Aspect and Spring Boot

Build Status

AspectJ lets you write aspects using Java annotations @Aspect and friends. Conveniently, but sometimes confusingly, Spring lets you use the same programming model, and then uses the AspectJ tooling APIs at runtime, so some people can’t tell the difference between Spring AOP and AspectJ. You don’t need any special tools to use Spring AOP, but it has it’s limitations, one of which is performance (you take a hit on startup while all the beans are analysed, and you take another smaller hit when the app is running and one of your aspects is executed through a proxy).

Luckily, it is quite easy to set up AspectJ to weave your code natively (not with Spring), and it is sometimes faster - just more steps to set up. In fact, there are multiple ways of using AspectJ to weave your code, some of which happen at runtime, and one (broadly speaking) that happens at compile time. Compile time is faster (unsurprisingly), but not massively (heuristically, maybe a 20% effect).

Note
The projects are updated with AspectJ 1.9.5 (included with Spring Boot 2.2.4) and use OpenJDK 11 now.
Note
AspectJ 1.8.13 (included with Spring Boot 1.5.9) has some major performance improvements affecting Spring AOP - the optimizations were suggested by running the benchmarks in this project. If you think Spring AOP might be slowing your app down on startup, upgrade now.

Contents

  • spring = Spring AOP standalone sample. Aspects and application code in the same module.

  • ltw = Load Time Weaving standalone sample. Aspects and application code in the same module.

  • ctw = Compile Time Weaving standalone sample. Aspects and application code in the same module.

  • multi-ltw = Load Time Weaving multi-module sample. Aspects and application code in separate modules.

  • multi-ctw = Compile Time Weaving multi-module sample. Aspects and application code in separate modules. The aspect library (as well as the application) has to be processed by AspectJ at build time.

  • timing = A utility library for logging timing data on startup for some internal features of Spring and Spring Boot

  • benchmarks = benchmarks for using AspectJ with the help of JMH (Java Microbenchmark Harness) for example of how to do microbenchmarking in Java. Also this article about JMH is a good place to start.

Converting from Spring AOP to AspectJ

You need to tell AspectJ where to find your aspects, and which classes you want it to weave. You also need to tell Spring not to try and weave the same aspects again (in Spring Boot you can do that with spring.aop.auto=false). The configuration for AspectJ lives in an XML file aop.xml, which can be in META-INF or in a package called org.aspectj. Here’s a simple example:

src/main/resources/org/aspectj/aop.xml
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
	<weaver>
		<include within="com.example.*" />
		<include within="org.springframework.boot..*" />
	</weaver>

	<aspects>
		<aspect name="com.example.Interceptor" />
	</aspects>

</aspectj>
Warning
If the AspectJ config file is in META-INF/aop.xml then the fat jar built by Spring Boot has it is in the wrong place, and there are nasty looking errors on startup. The app still works and the aspects are woven, but you can work around it by putting aop.xml in the org.aspectj package instead of in META-INF.

Load Time Weaving

One of the runtime options is called "load time weaving", and Spring even has an annotation @EnableLoadTimeWeaving to help get it off the ground. The Spring annotation is rooted in the culture and mechanics of application servers - it only makes sense if you have multiple apps running in the same JVM with class loader isolation. What happens is that it uses a special ClassLoader that manipulates the classes as they are loaded.

The other option for load time weaving is the AspectJ agent, which you add to the JVM on the command line, and it can look at all the classes and potentially weave them with aspects.

E.g. :

$ cd ltw
$ mvn clean install
$ java -javaagent:$HOME/.m2/repository/org/aspectj/aspectjweaver/[version]/aspectjweaver-[version].jar -jar target/*.jar

You can also use the copied version of aspectweaver-[version].jar in the target/aspectj directory of the Maven project, since it is copied to that directory with Maven Dependency plugin.

$ java -javaagent:target/aspectj/aspectjweaver-[version].jar -jar target/*.jar

If you don’t add the agent (and don’t provide an implementation of Interceptor.aspectOf()) you might get a confusing "cyclic dependency" error from Spring on startup. It’s not really cyclic, but because the Interceptor in this sample is an @EventListener Spring is trying to create it very early and gets confused. The real problem is just that Aspects.aspectOf() doesn’t work unless the agent is attached.

Note
@EnableLoadTimeWeaving doesn’t actually make much sense in a Spring Boot app that is going to run in its own process - you can just add the AspectJ agent. Many people confuse "load time weaving" with "runtime weaving" generally (because for a long time it was the only option for many Spring apps). So if someone asks you to implement "load time weaving" in a Spring Boot app, just add the agent.
Note
The "timing" library is a dependency of this project so it gets woven at runtime and prints out interesting (but verbose) information about timings for bean initialization. This is in addition to the aspects library.

Compile Time Weaving

To weave the aspects at compile time (and also optionally use the AspectJ language, as opposed to Java with annotations), you need an additional plugin in your build. If all you need is to weave existing byte code, the plugin configuration is very simple:

<plugin>
  <groupId>org.codehaus.mojo</groupId>                   (3)
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.10</version>
  <configuration>
    <source>${java.version}</source>
    <target>${java.version}</target>
    <proc>none</proc>                                    (1)
    <complianceLevel>${java.version}</complianceLevel>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
      </goals>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>${aspectj.version}</version>               (2)
    </dependency>
  </dependencies>
</plugin>
  1. Useful if you have annotation processors (like Spring Boot configuration processor), to avoid them being processed again by the AspectJ compiler.

  2. Optionally update the AspectJ tooling to the latest version. The aspectrt jar has to be included separately.

  3. See the note below for Java 11

In this sample build the app with the weave profile to run this plugin. E.g.

$ cd ctw
$ mvn clean install
$ java -jar target/*.jar
Note
for Java 11 you cannot use org.codehaus.mojo::aspectj-maven-plugin because the plugin is not developed anymore, see mojohaus/aspectj-maven-plugin#49. Instead use https://github.com/nickwongdev/aspectj-maven-plugin with com.nickwongdev::aspectj-maven-plugin
Note
in the plugin configuration above, we haven’t asked AspectJ to weave the dependencies, and it won’t do that by default. Consequently we won’t see as much output from the app when it runs as we did with the runtime weaving (where all the classes were available for weaving as soon as they were loaded).
Note
AspectJ is smart enough not to try and weave the same class twice, so you can always add the agent at runtime even when the application classes are already woven. That would be one way to pick up additional join points that you hadn’t woven at compile time.
Note
The "timing" library is not a dependency of this project, and there wouldn’t be much point doing that because the pointcuts it defines would not match anything that was being compiled here.

Running the LTW Sample

You can run the samples from the command line and see the aspect logging to stderr:

$ cd ltw
$ mvn spring-boot:run
...
execution(InterceptorApplication..EnhancerBySpringCGLIB..8ce66f62.setBeanFactory(..))
execution(InterceptorApplication..EnhancerBySpringCGLIB..8ce66f62.setBeanFactory(..))
...

To run in the IDE you need to add the agent to your launch configuration.

-javaagent:${system_property:user.home}/.m2/repository/org/aspectj/aspectjweaver/[version]/aspectjweaver-[version].jar

or simply

-javaagent:target/aspectj/aspectjweaver-[version].jar

Note that you could add @EnableLoadTimeWeaving to the main application class, but it should probably be removed, as it’s misleading.

There’s an open issue asking for @EnableLoadTimeWeaving support in Spring Boot, and a user who says he made it work with a PropertiesLauncher (because it can set the class loader really early): spring-projects/spring-boot#739. It doesn’t work to set the classloader in the main method because too many Spring Boot classes have already been loaded by then, but there is a trick you can play with [attaching the agent at runtime](http://www.eclipse.org/aspectj/doc/released/README-187.html) (in which case all classes loaded up to that point can not be woven).

Note
You can enable logging of the weaving using -Daj.weaving.verbose=true.

Run the CTW Sample

$ cd ctw
$ mvn spring-boot:run

The compile time weaving example does not need any Java agent.

More Repositories

1

spring-boot-angular

Quick tutorial on how to create a Spring Boot app with Angular front end using Maven and modern front end tooling
TypeScript
342
star
2

spring-boot-startup-bench

Benchmarks for Spring Boot startup
Java
294
star
3

spring-boot-memory-blog

Spring Boot Memory Performance Blog
152
star
4

sparklr-boot

Demo OAuth2 provider with Spring Boot
Java
137
star
5

spring-boot-micro-apps

Java
131
star
6

kubernetes-intro

Shell
119
star
7

spring-boot-legacy

Support for legacy (Servlet 2.5) apps in Spring Boot
Java
100
star
8

spring-boot-allocations

Java
99
star
9

reactive-notes

Java
89
star
10

spring-security-architecture

High level documentation for Spring Security and users of Spring Boot
79
star
11

inner-loop-boot-k8s

Java
65
star
12

spring-boot-ratpack

Spring Boot wrapper for Ratpack
Java
53
star
13

spring-boot-jersey

Jersey autoconfig support for Spring Boot
Java
51
star
14

spring-boot-java-10

Java
36
star
15

spring-security-rsa

Java
30
star
16

spring-boot-operator

Go
29
star
17

main-branch-switch

Scripts for switching a Github repository to use a "main" branch
Shell
25
star
18

mustache-sample

Java
24
star
19

spring-boot-js-demo

These samples explore the different options that Spring Boot developers have for using Javascript and CSS on the client (browser) side of their application.
Java
23
star
20

rsocket-test-server

Java
23
star
21

spring-boot-sample-data-eclipselink

Java
23
star
22

dist-tx

Source code for distributed transactions article from 2008, updated to use Spring Boot
Java
19
star
23

dependency-hell

Short article on a dependency management issue with Maven 3.3
Shell
16
star
24

docker-services

Dockerfile
15
star
25

spring-oauth2-integration-tests

Integration tests and demo apps for OAuth2 with Spring
Java
14
star
26

spring-boot-mustache

Spring Boot autoconfiguration for JMutsache (web and nonweb template rendering)
Java
14
star
27

spring-boot-auto-reflect

Java
13
star
28

spring-boot-spa

Shell
12
star
29

spring-batch-gemfire

Gemfire integration for Spring Batch
Java
12
star
30

protobuf-wasm

Shell
12
star
31

presos

Presentations for conferences and user groups etc.
HTML
11
star
32

frontend-microservices

Java
11
star
33

auth-server-client

Shell
11
star
34

log4j-utils

Log4j Utilities
Java
10
star
35

spring-todo-mvc

Java
10
star
36

skaffold-devtools-demo

Java
9
star
37

spring-batch-gridgain

GridGain integration for Spring Batch
Java
8
star
38

spring-wasm-demo

C
8
star
39

native-grpc

Java
7
star
40

spring-boot-initializer

Java
6
star
41

payments-demo

Java
6
star
42

spring-security-oauth2-hydra

Java
6
star
43

spring-boot-aot

Java
6
star
44

cloud-middleware-blog

Blog text and sample project for article on spring.io in 2015
Java
6
star
45

qcon-workshop-2016

Shell
6
star
46

spring-boot-lazy-actuator

Java
5
star
47

hello-wasm

C
5
star
48

http-amqp-tunnel

Tunnel HTTP over AMQP using Spring Integration
Java
5
star
49

spring-boot-features

Java
5
star
50

spring-spreadsheet

Spring spreadsheet support (Excel, OpenOffice etc.)
Java
5
star
51

gs-spring-boot-docker

Spring Boot with Docker :: Learn how to create a Docker container from a Spring Boot application with Maven or Gradle
Java
5
star
52

two-factor

Shell
4
star
53

spring-boot-factory-aspects

Java
4
star
54

java-function-benchmarks

Java
4
star
55

riff-http

Shell
4
star
56

spring-data-simple

Simple Repository metadata for repositories created "manually" (i.e. not auto-generated)
Java
4
star
57

stream-startup

Java
4
star
58

jlink-petclinic

Dockerfile
4
star
59

spring-batch-grid

Grid adapters for Spring Batch
Java
4
star
60

lambda-aws-demo

Demo for AWS custom runtime native image
Java
4
star
61

nix-config

Emacs Lisp
4
star
62

async-wasm

C
4
star
63

refresh

Java
4
star
64

cflogin

Authorization Server for "fully-leaded" Cloud Foundry access tokens
Java
3
star
65

spring-config-operator

Go
3
star
66

openapi-rust

Rust
3
star
67

spring-boot-legacy-agent

Provides a Java agent that allows an app that was compiled with Spring Boot 2.0 to run with earlier versions.
Java
3
star
68

spring-restdocs-messaging

Java
2
star
69

spring-boot-proto

Java
2
star
70

petflix

Java
2
star
71

pod-mutating-webhook

Go
2
star
72

simple-gateway

simple-gateway
2
star
73

spring-petclinic-jpa

Java
2
star
74

gateway-wasm

Java
2
star
75

spring-boot-archetypes

Automation scripts for publishing Spring Boot Samples as Maven archetypes
Shell
2
star
76

SpringCloudWorkshop

TSQL
2
star
77

spring-controller

Java
2
star
78

cf-memory-tests

Java
2
star
79

openapi-demo

Java
2
star
80

sagan-wiki

2
star
81

nix-demo

Dockerfile
2
star
82

spring-xd-module-runner

2
star
83

native-config-server

Dockerfile
2
star
84

spring-cloud-stream-binder-servlet

Java
2
star
85

js-utils

JavaScript
1
star
86

ubuntu-make-vm-images

Shell
1
star
87

teavm-demo

Java
1
star
88

nix-cloud

Shell
1
star
89

spring-oauth2-integration-tests-xml

Integration tests and demo apps for OAuth2 with Spring using XML for the OAuth bits
Java
1
star
90

vanilla-orm

Java
1
star
91

spring-boot-bindings

Go
1
star
92

dotnet-test

Get dotnet working on Linux
Dockerfile
1
star
93

github-admin

Java
1
star
94

doppler-metrics-sample

Java
1
star
95

azure-custom-handler

HCL
1
star
96

spring-cloud-deployer-thin

Java
1
star
97

spring-service-operator

Go
1
star
98

hello-nix-java

Java
1
star
99

hello-rust

Java
1
star
100

dispatcher-servlet-container

Java
1
star