├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── README.adoc ├── benchmarks ├── README.adoc ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ ├── aspects │ │ │ ├── ServiceInterceptor1.java │ │ │ ├── ServiceInterceptor10.java │ │ │ ├── ServiceInterceptor11.java │ │ │ ├── ServiceInterceptor12.java │ │ │ ├── ServiceInterceptor13.java │ │ │ ├── ServiceInterceptor14.java │ │ │ ├── ServiceInterceptor15.java │ │ │ ├── ServiceInterceptor16.java │ │ │ ├── ServiceInterceptor17.java │ │ │ ├── ServiceInterceptor18.java │ │ │ ├── ServiceInterceptor19.java │ │ │ ├── ServiceInterceptor2.java │ │ │ ├── ServiceInterceptor20.java │ │ │ ├── ServiceInterceptor3.java │ │ │ ├── ServiceInterceptor4.java │ │ │ ├── ServiceInterceptor5.java │ │ │ ├── ServiceInterceptor6.java │ │ │ ├── ServiceInterceptor7.java │ │ │ ├── ServiceInterceptor8.java │ │ │ └── ServiceInterceptor9.java │ │ │ └── example │ │ │ ├── Interceptor.java │ │ │ ├── InterceptorApplication.java │ │ │ └── MultiBeanConfiguration.java │ └── resources │ │ ├── application.properties │ │ └── org │ │ └── aspectj │ │ └── aop.xml │ └── test │ └── java │ └── com │ ├── bench │ ├── ProcessLauncherState.java │ ├── ProcessLauncherStateTest.java │ └── StartupBenchmark.java │ └── example │ └── InterceptorApplicationTests.java ├── ctw ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Interceptor.java │ │ │ └── InterceptorApplication.java │ └── resources │ │ ├── application.properties │ │ └── org │ │ └── aspectj │ │ └── aop.xml │ └── test │ └── java │ └── com │ └── example │ └── InterceptorApplicationTests.java ├── ltw ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Interceptor.java │ │ │ └── InterceptorApplication.java │ └── resources │ │ ├── application.properties │ │ └── org │ │ └── aspectj │ │ └── aop.xml │ └── test │ └── java │ └── com │ └── example │ └── InterceptorApplicationTests.java ├── multi-ctw ├── ctw-app │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── InterceptorApplication.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── org │ │ │ └── aspectj │ │ │ └── aop.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── InterceptorApplicationTests.java ├── ctw-aspects │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── example │ │ └── Interceptor.java └── pom.xml ├── multi-ltw ├── ltw-app │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── InterceptorApplication.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── org │ │ │ └── aspectj │ │ │ └── aop.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── InterceptorApplicationTests.java ├── ltw-aspects │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── example │ │ └── Interceptor.java └── pom.xml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── spring ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Interceptor.java │ │ │ └── InterceptorApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── InterceptorApplicationTests.java └── timing ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── springframework │ │ └── boot │ │ └── aspects │ │ ├── AspectConfiguration.java │ │ └── TimingInterceptor.java └── resources │ └── META-INF │ ├── aop.xml │ └── spring.factories └── test └── java └── org └── springframework └── boot └── aspects ├── DemoApplication.java └── DemoApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | dependency-reduced-pom.xml 4 | interpolated-pom.xml 5 | .#* 6 | *# 7 | *~ 8 | build.log 9 | _site/ 10 | .vscode/ 11 | 12 | ### STS ### 13 | .apt_generated 14 | .classpath 15 | .factorypath 16 | .project 17 | .settings 18 | .springBeans 19 | *.DS_Store* 20 | 21 | ### IntelliJ IDEA ### 22 | .idea 23 | *.iws 24 | *.iml 25 | *.ipr 26 | 27 | ### NetBeans ### 28 | nbproject/private/ 29 | build/ 30 | nbbuild/ 31 | dist/ 32 | nbdist/ 33 | .nb-gradle/ 34 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsyer/spring-boot-aspectj/79f5f76a398657bd846045b33621375f43c24aef/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: mvn clean install 3 | 4 | cache: 5 | directories: 6 | - $HOME/.m2/repository 7 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | == Sample Apps Showing How to Use AspectJ Natively with `@Aspect` and Spring Boot 2 | 3 | image:https://travis-ci.com/lofidewanto/spring-boot-aspectj.svg?branch=master["Build Status", link="https://travis-ci.com/lofidewanto/spring-boot-aspectj"] 4 | 5 | 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). 6 | 7 | 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). 8 | 9 | NOTE: The projects are updated with AspectJ 1.9.5 (included with Spring Boot 2.2.4) and use OpenJDK 11 now. 10 | 11 | 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. 12 | 13 | == Contents 14 | 15 | * spring = Spring AOP standalone sample. Aspects and application code in the same module. 16 | * ltw = Load Time Weaving standalone sample. Aspects and application code in the same module. 17 | * ctw = Compile Time Weaving standalone sample. Aspects and application code in the same module. 18 | * multi-ltw = Load Time Weaving multi-module sample. Aspects and application code in separate modules. 19 | * 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. 20 | * timing = A utility library for logging timing data on startup for some internal features of Spring and Spring Boot 21 | * benchmarks = benchmarks for using AspectJ with the help of https://www.baeldung.com/java-microbenchmark-harness[JMH (Java Microbenchmark Harness)] for example of how to do microbenchmarking in Java. Also this article about http://tutorials.jenkov.com/java-performance/jmh.html[JMH] is a good place to start. 22 | 23 | == Converting from Spring AOP to AspectJ 24 | 25 | 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 https://eclipse.org/aspectj/doc/next/devguide/ltw-configuration.html[XML file] `aop.xml`, which can be in `META-INF` or in a package called `org.aspectj`. Here's a simple example: 26 | 27 | .src/main/resources/org/aspectj/aop.xml 28 | [source,xml] 29 | ---- 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ---- 43 | 44 | 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 https://github.com/spring-projects/spring-boot/issues/7587[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`. 45 | 46 | == Load Time Weaving 47 | 48 | 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. 49 | 50 | 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. 51 | 52 | E.g. : 53 | 54 | ``` 55 | $ cd ltw 56 | $ mvn clean install 57 | $ java -javaagent:$HOME/.m2/repository/org/aspectj/aspectjweaver/[version]/aspectjweaver-[version].jar -jar target/*.jar 58 | ``` 59 | 60 | 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. 61 | 62 | ``` 63 | $ java -javaagent:target/aspectj/aspectjweaver-[version].jar -jar target/*.jar 64 | ``` 65 | 66 | 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. 67 | 68 | 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. 69 | 70 | 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. 71 | 72 | == Compile Time Weaving 73 | 74 | 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: 75 | 76 | [source,xml] 77 | ---- 78 | 79 | org.codehaus.mojo <3> 80 | aspectj-maven-plugin 81 | 1.10 82 | 83 | ${java.version} 84 | ${java.version} 85 | none <1> 86 | ${java.version} 87 | 88 | 89 | 90 | 91 | compile 92 | 93 | 94 | 95 | 96 | 97 | org.aspectj 98 | aspectjtools 99 | ${aspectj.version} <2> 100 | 101 | 102 | 103 | ---- 104 | <1> Useful if you have annotation processors (like Spring Boot configuration processor), to avoid them being processed again by the AspectJ compiler. 105 | <2> Optionally update the AspectJ tooling to the latest version. The `aspectrt` jar has to be included separately. 106 | <3> See the note below for Java 11 107 | 108 | In this sample build the app with the `weave` profile to run this plugin. E.g. 109 | 110 | ``` 111 | $ cd ctw 112 | $ mvn clean install 113 | $ java -jar target/*.jar 114 | ``` 115 | 116 | NOTE: for Java 11 you cannot use org.codehaus.mojo::aspectj-maven-plugin because the plugin is not developed anymore, see https://github.com/mojohaus/aspectj-maven-plugin/issues/49. Instead use https://github.com/nickwongdev/aspectj-maven-plugin with com.nickwongdev::aspectj-maven-plugin 117 | 118 | 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). 119 | 120 | 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. 121 | 122 | 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. 123 | 124 | == Running the LTW Sample 125 | 126 | You can run the samples from the command line and see the aspect logging to stderr: 127 | 128 | ``` 129 | $ cd ltw 130 | $ mvn spring-boot:run 131 | ... 132 | execution(InterceptorApplication..EnhancerBySpringCGLIB..8ce66f62.setBeanFactory(..)) 133 | execution(InterceptorApplication..EnhancerBySpringCGLIB..8ce66f62.setBeanFactory(..)) 134 | ... 135 | ``` 136 | 137 | To run in the IDE you need to add the agent to your launch configuration. 138 | 139 | ``` 140 | -javaagent:${system_property:user.home}/.m2/repository/org/aspectj/aspectjweaver/[version]/aspectjweaver-[version].jar 141 | ``` 142 | 143 | or simply 144 | 145 | ``` 146 | -javaagent:target/aspectj/aspectjweaver-[version].jar 147 | ``` 148 | 149 | Note that you could add `@EnableLoadTimeWeaving` to the main application class, but it should probably be removed, as it's misleading. 150 | 151 | 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): https://github.com/spring-projects/spring-boot/issues/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). 152 | 153 | NOTE: You can enable logging of the weaving using `-Daj.weaving.verbose=true`. 154 | 155 | == Run the CTW Sample 156 | 157 | ``` 158 | $ cd ctw 159 | $ mvn spring-boot:run 160 | ``` 161 | 162 | The compile time weaving example does not need any Java agent. 163 | 164 | == Useful Links 165 | 166 | * https://stackoverflow.com/questions/21350966/using-autowired-with-aspectj-and-springboot/21367986 167 | * https://stackoverflow.com/questions/12423965/maven-aspectj-all-steps-to-configure-it 168 | * https://stackoverflow.com/questions/40472614/simple-configurable-with-modern-spring-boot-gradle 169 | * https://www.eclipse.org/aspectj/doc/released/README-187.html 170 | * https://github.com/spring-projects/spring-boot/issues/6626 171 | * https://github.com/spring-projects/spring-boot/issues/7587 172 | * https://github.com/spring-projects/spring-boot/issues/739 173 | -------------------------------------------------------------------------------- /benchmarks/README.adoc: -------------------------------------------------------------------------------- 1 | = Benchmarks 2 | 3 | == How to run 4 | 5 | The Surefire Maven Plugin will run the benchmarking process: 6 | 7 | ``` 8 | $ cd benchmarks 9 | $ mvn test -Dtest=StartupBenchmark 10 | ``` 11 | 12 | Outside Maven after building the benchmarks.jar you can just run the `StartupBenchmark` in your IDE. 13 | 14 | = Results 15 | 16 | === JDK 11 17 | 18 | ``` 19 | class method scale median mean range 20 | com.bench.StartupBenchmark ltw 2.398 2.473 0.113 21 | com.bench.StartupBenchmark ltw_100 2.404 2.431 0.037 22 | com.bench.StartupBenchmark spring v0_10 1.604 1.648 0.039 23 | com.bench.StartupBenchmark spring v1_10 1.714 1.748 0.030 24 | com.bench.StartupBenchmark spring v1_100 1.767 1.792 0.019 25 | com.bench.StartupBenchmark spring v10_50 2.204 2.284 0.062 26 | com.bench.StartupBenchmark spring v20_50 2.801 2.828 0.033 27 | com.bench.StartupBenchmark spring a0_10 1.621 1.659 0.042 28 | com.bench.StartupBenchmark spring a1_10 1.704 1.772 0.139 29 | com.bench.StartupBenchmark spring a1_100 1.700 1.774 0.157 30 | com.bench.StartupBenchmark spring a10_50 2.004 2.104 0.146 31 | com.bench.StartupBenchmark spring a10_100 1.943 1.988 0.084 32 | com.bench.StartupBenchmark spring a20_50 2.216 2.268 0.056 33 | ``` 34 | 35 | === JDK 8 36 | 37 | ``` 38 | class method scale median mean range 39 | com.bench.StartupBenchmark ltw 2.020 2.044 0.063 40 | com.bench.StartupBenchmark ltw_100 2.050 2.078 0.042 41 | com.bench.StartupBenchmark spring v0_10 1.532 1.550 0.018 42 | com.bench.StartupBenchmark spring v1_10 1.621 1.662 0.051 43 | com.bench.StartupBenchmark spring v1_100 1.653 1.669 0.026 44 | com.bench.StartupBenchmark spring v10_50 2.120 2.148 0.036 45 | com.bench.StartupBenchmark spring v20_50 2.657 2.692 0.034 46 | com.bench.StartupBenchmark spring a0_10 1.517 1.537 0.025 47 | com.bench.StartupBenchmark spring a1_10 1.624 1.638 0.019 48 | com.bench.StartupBenchmark spring a1_100 1.651 1.670 0.015 49 | com.bench.StartupBenchmark spring a10_50 1.905 1.927 0.020 50 | com.bench.StartupBenchmark spring a10_100 1.900 1.931 0.035 51 | com.bench.StartupBenchmark spring a20_50 2.124 2.162 0.052 52 | ``` 53 | 54 | == Older Results 55 | 56 | === AspectJ 1.8.11 Snapshots 57 | 58 | (Seems to fix the problem with Spring AOP.) 59 | 60 | ``` 61 | Benchmark (scale) Mode Cnt Score Error Units 62 | StartupBenchmark.ltw N/A avgt 10 1.878 ± 0.039 s/op 63 | StartupBenchmark.ltw_100 N/A avgt 10 1.930 ± 0.083 s/op 64 | StartupBenchmark.spring v0_10 avgt 10 1.485 ± 0.033 s/op 65 | StartupBenchmark.spring v1_10 avgt 10 1.605 ± 0.069 s/op 66 | StartupBenchmark.spring v1_100 avgt 10 1.629 ± 0.022 s/op 67 | StartupBenchmark.spring v10_50 avgt 10 2.176 ± 0.091 s/op 68 | StartupBenchmark.spring v20_50 avgt 10 2.771 ± 0.080 s/op 69 | StartupBenchmark.spring a0_10 avgt 10 1.485 ± 0.049 s/op 70 | StartupBenchmark.spring a1_10 avgt 10 1.564 ± 0.032 s/op 71 | StartupBenchmark.spring a1_100 avgt 10 1.603 ± 0.047 s/op 72 | StartupBenchmark.spring a10_50 avgt 10 1.831 ± 0.013 s/op 73 | StartupBenchmark.spring a10_100 avgt 10 1.890 ± 0.060 s/op 74 | StartupBenchmark.spring a20_50 avgt 10 2.121 ± 0.083 s/op 75 | ``` 76 | 77 | === AspectJ 1.8.10 78 | 79 | ``` 80 | Benchmark Mode Cnt Score Error Units 81 | StartupBenchmark.null avgt 10 2.114 ± 0.134 s/op 82 | StartupBenchmark.ltw avgt 10 2.749 ± 0.067 s/op 83 | StartupBenchmark.ltw_10 avgt 10 2.914 ± 0.110 s/op 84 | StartupBenchmark.ltw_10_100 avgt 10 2.873 ± 0.114 s/op 85 | StartupBenchmark.ltw_20 avgt 10 2.900 ± 0.110 s/op 86 | StartupBenchmark.ltw_20_100 avgt 10 2.965 ± 0.114 s/op 87 | StartupBenchmark.annotation avgt 10 2.113 ± 0.095 s/op 88 | StartupBenchmark.annotation_10_100 avgt 10 7.204 ± 0.062 s/op 89 | StartupBenchmark.annotation_10_50 avgt 10 7.199 ± 0.092 s/op 90 | StartupBenchmark.annotation_1_100 avgt 10 2.838 ± 0.115 s/op 91 | StartupBenchmark.annotation_1_50 avgt 10 2.814 ± 0.070 s/op 92 | StartupBenchmark.annotation_20_100 avgt 10 11.512 ± 0.106 s/op 93 | StartupBenchmark.annotation_20_50 avgt 10 11.476 ± 0.132 s/op 94 | ``` 95 | 96 | .Number of @Aspects vs. Startup Time 97 | image::https://docs.google.com/spreadsheets/d/e/2PACX-1vR8B4l5WkWf-9gZWmIYTkmBWM7YWf5bRg852OakrV0G2-vtfM_UkVNRC3cTVk1079HagnMVHYZnvbib/pubchart?oid=756916910&format=image[] 98 | 99 | Legend: 100 | 101 | * null: No aspect weaving at all. 102 | * annotation: Spring AOP. No aspects with method annotation pointcuts. 103 | * annotation_1_50: Spring AOP with extra aspects(1) and beans(50). 104 | * annotation_1_100: Spring AOP with extra aspects(1) and beans(100). 105 | * annotation_10_50: Spring AOP with extra aspects(10) and beans(50). 106 | * annotation_10_50: Spring AOP with extra aspects(10) and beans(100). 107 | * annotation_20_50: Spring AOP with extra aspects(20) and beans(50). 108 | * annotation_20_50: Spring AOP with extra aspects(20) and beans(100). 109 | * ltw: Load Time Weaving. Aspects woven by AspectJ agent, not Spring. 110 | * ltw_10: Load Time Weaving with extra aspects (10). 111 | * ltw_10_100: Load Time Weaving with extra aspects(10) and beans(100). 112 | * ltw_20: Load Time Weaving with extra aspects (20). 113 | * ltw_20_100: Load Time Weaving with extra aspects(20) and beans(100). 114 | 115 | |=== 116 | | sample | @aspects | beans | startup(millis) 117 | 118 | | null | 0 | 188 | 2117 119 | | ltw | 0 | 188 | 2749 120 | | ltw_10 | 10| 188 | 2914 121 | | ltw_10_100 | 10| 288 | 2873 122 | | ltw_20 | 20| 188 | 2900 123 | | ltw_20_100 | 20| 288 | 2965 124 | | annotation | 0 | 191 | 2113 125 | | annotation_1_50 | 1 | 242 | 2814 126 | | annotation_1_100 | 1 | 292 | 2838 127 | | annotation_10_50 | 10| 251 | 7119 128 | | annotation_10_100 | 10| 301 | 7204 129 | | annotation_20_50 | 20| 261 | 11476 130 | | annotation_20_100 | 20| 311 | 11512 131 | 132 | 133 | |=== 134 | 135 | The annotation (Spring AOP) samples are much slower with @aspects than 136 | without and the slow down is proportional to the number of pointcuts 137 | (not so much with the number of beans). It's pretty awful: 400ms per 138 | pointcut. 139 | 140 | The "ltw" samples are a bit slower with @aspects than without, but the 141 | slow down is not proportional to the number of pointcuts. Note, 142 | however, that all the pointcuts were the same, so maybe there is some 143 | optimization in AspectJ that doesn't help for a realistic system. 144 | -------------------------------------------------------------------------------- /benchmarks/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | benchmarks 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | benchmarks 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.2.4.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 8 26 | 1.23 27 | 1.0.24.RELEASE 28 | org.openjdk.jmh.Main 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-actuator 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-aop 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-web 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-configuration-processor 47 | true 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | 57 | org.openjdk.jmh 58 | jmh-core 59 | ${jmh.version} 60 | 61 | 62 | 63 | org.openjdk.jmh 64 | jmh-generator-annprocess 65 | ${jmh.version} 66 | provided 67 | 68 | 69 | 70 | com.github.mp911de.microbenchmark-runner 71 | microbenchmark-runner-junit5 72 | 0.2.0.RELEASE 73 | test 74 | 75 | 76 | com.github.mp911de.microbenchmark-runner 77 | microbenchmark-runner-extras 78 | 0.2.0.RELEASE 79 | test 80 | 81 | 82 | 83 | org.springframework.boot 84 | spring-boot-starter-test 85 | test 86 | 87 | 88 | junit 89 | junit 90 | 91 | 92 | org.junit.vintage 93 | junit-vintage-engine 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | tools.jar 103 | 104 | [1.8,1.9) 105 | 106 | 107 | 108 | com.sun 109 | tools 110 | 1.8 111 | system 112 | ${java.home}/../lib/tools.jar 113 | 114 | 115 | 116 | 117 | 118 | 119 | benchmarks 120 | 121 | 122 | org.apache.maven.plugins 123 | maven-compiler-plugin 124 | 125 | 126 | 127 | org.openjdk.jmh 128 | jmh-generator-annprocess 129 | ${jmh.version} 130 | 131 | 132 | ${java.version} 133 | ${java.version} 134 | 135 | 136 | 137 | 138 | maven-deploy-plugin 139 | 140 | true 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | jitpack.io 149 | https://jitpack.io 150 | 151 | 152 | spring-snapshots 153 | Spring Snapshots 154 | https://repo.spring.io/snapshot 155 | 156 | true 157 | 158 | 159 | 160 | spring-milestones 161 | Spring Milestones 162 | https://repo.spring.io/milestone 163 | 164 | false 165 | 166 | 167 | 168 | 169 | 170 | spring-snapshots 171 | Spring Snapshots 172 | https://repo.spring.io/snapshot 173 | 174 | true 175 | 176 | 177 | 178 | spring-milestones 179 | Spring Milestones 180 | https://repo.spring.io/milestone 181 | 182 | false 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor1 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor10.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor10 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor11.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor11 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor12.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor12 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor13.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor13 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor14.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor14 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor15.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor15 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor16.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor16 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor17.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor17 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor18.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor18 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor19.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor19 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor2.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor2 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor20.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor20 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor3 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor4 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor5.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor5 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor6.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Copyright 2016-2017 the original author or authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package com.aspects; 19 | 20 | import org.aspectj.lang.ProceedingJoinPoint; 21 | import org.aspectj.lang.annotation.Around; 22 | import org.aspectj.lang.annotation.Aspect; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | @Aspect 29 | class ServiceInterceptor6 { 30 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor7.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor7 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor8.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor8 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/aspects/ServiceInterceptor9.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.aspects; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | /** 24 | * @author Dave Syer 25 | * 26 | */ 27 | @Aspect 28 | class ServiceInterceptor9 { 29 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* *.*(..))") 30 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 31 | Object result = joinPoint.proceed(); 32 | System.err.println(joinPoint.toShortString() + ": " + result); 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.context.event.ContextRefreshedEvent; 9 | import org.springframework.context.event.EventListener; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Aspect 13 | @ConfigurationProperties("interceptor") 14 | @Component 15 | public class Interceptor { 16 | 17 | /** 18 | * Message to print on startup 19 | */ 20 | private String message = "Up"; 21 | 22 | public String getMessage() { 23 | return message; 24 | } 25 | 26 | public void setMessage(String message) { 27 | this.message = message; 28 | } 29 | 30 | @Around("execution(* *.*(..)) && within(com.example..*)") 31 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 32 | Object result = joinPoint.proceed(); 33 | System.err.println(joinPoint.toShortString() + ": " + result); 34 | return result; 35 | } 36 | 37 | @EventListener 38 | public void started(ContextRefreshedEvent event) { 39 | System.err.println(message + ": " + event); 40 | System.err.println("Beans: " + event.getApplicationContext().getBeanDefinitionCount()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @SpringBootApplication 9 | @RestController 10 | public class InterceptorApplication { 11 | 12 | @RequestMapping("/") 13 | public String home() { 14 | return "Hello World"; 15 | } 16 | 17 | public static void main(String[] args) { 18 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /benchmarks/src/main/java/com/example/MultiBeanConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.aspectj.lang.ProceedingJoinPoint; 20 | import org.aspectj.lang.annotation.Around; 21 | import org.aspectj.lang.annotation.Aspect; 22 | 23 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 24 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 25 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.context.annotation.Import; 28 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 29 | import org.springframework.core.env.ConfigurableEnvironment; 30 | import org.springframework.core.type.AnnotationMetadata; 31 | 32 | /** 33 | * @author Dave Syer 34 | * 35 | */ 36 | @Configuration 37 | @Import(MultiBeanSelector.class) 38 | public class MultiBeanConfiguration { 39 | } 40 | 41 | class Service { 42 | public void execute() { 43 | } 44 | } 45 | 46 | @Aspect 47 | class ServiceInterceptor { 48 | @Around("execution (* com.example..*(..))") 49 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 50 | Object result = joinPoint.proceed(); 51 | System.err.println(joinPoint.toShortString() + ": " + result); 52 | return result; 53 | } 54 | } 55 | 56 | @Aspect 57 | class AnnotationInterceptor { 58 | @Around("@annotation(org.springframework.scheduling.annotation.Async) && execution (* com.example..*(..))") 59 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 60 | Object result = joinPoint.proceed(); 61 | System.err.println(joinPoint.toShortString() + ": " + result); 62 | return result; 63 | } 64 | } 65 | 66 | class MultiBeanSelector implements ImportBeanDefinitionRegistrar { 67 | 68 | private static int beans = 0; 69 | 70 | private static int aspects = 0; 71 | 72 | @Override 73 | public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, 74 | BeanDefinitionRegistry registry) { 75 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) registry; 76 | ConfigurableEnvironment environment = (ConfigurableEnvironment) beanFactory 77 | .getSingleton("environment"); 78 | int total = environment.getProperty("bench.beans", Integer.class, 0); 79 | for (int i = beans; i < beans + total; i++) { 80 | registry.registerBeanDefinition("service" + i, BeanDefinitionBuilder 81 | .rootBeanDefinition(Service.class).getBeanDefinition()); 82 | } 83 | beans += total; 84 | total = environment.getProperty("bench.aspects", Integer.class, 0); 85 | Class interceptorType = ServiceInterceptor.class; 86 | if (environment.getProperty("bench.annotation", Boolean.class, false)) { 87 | interceptorType = AnnotationInterceptor.class; 88 | } 89 | for (int i = aspects; i < aspects + total; i++) { 90 | registry.registerBeanDefinition("aspect" + i, BeanDefinitionBuilder 91 | .rootBeanDefinition(interceptorType).getBeanDefinition()); 92 | } 93 | aspects += total; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /benchmarks/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsyer/spring-boot-aspectj/79f5f76a398657bd846045b33621375f43c24aef/benchmarks/src/main/resources/application.properties -------------------------------------------------------------------------------- /benchmarks/src/main/resources/org/aspectj/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /benchmarks/src/test/java/com/bench/ProcessLauncherState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.bench; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.InputStreamReader; 23 | import java.net.MalformedURLException; 24 | import java.net.URL; 25 | import java.net.URLClassLoader; 26 | import java.nio.file.Paths; 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | import org.openjdk.jmh.util.Utils; 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | import org.springframework.boot.system.JavaVersion; 35 | 36 | import com.example.InterceptorApplication; 37 | 38 | public class ProcessLauncherState { 39 | 40 | private static final Logger logger = LoggerFactory.getLogger(ProcessLauncherState.class); 41 | 42 | private Process started; 43 | private List args; 44 | private List progArgs; 45 | private List jvmArgs; 46 | private File home; 47 | private String mainClass = InterceptorApplication.class.getName(); 48 | private int length; 49 | 50 | public ProcessLauncherState(String dir, String... args) { 51 | this.args = new ArrayList<>(Arrays.asList(args)); 52 | int count = 0; 53 | this.args.add(count++, System.getProperty("java.home") + "/bin/java"); 54 | this.args.add(count++, "-Xmx128m"); 55 | this.args.add(count++, "-cp"); 56 | this.args.add(count++, getClasspath()); 57 | this.args.add(count++, "-Djava.security.egd=file:/dev/./urandom"); 58 | this.args.add(count++, "-XX:TieredStopAtLevel=1"); // zoom 59 | if (System.getProperty("bench.args") != null) { 60 | this.args.addAll(count++, Arrays.asList(System.getProperty("bench.args").split(" "))); 61 | } 62 | this.length = args.length; 63 | this.home = new File(dir); 64 | } 65 | 66 | public void setMainClass(String mainClass) { 67 | this.mainClass = mainClass; 68 | } 69 | 70 | public void setProgArgs(String... extraArgs) { 71 | this.progArgs = Arrays.asList(extraArgs); 72 | } 73 | 74 | public void setJvmArgs(String... extraArgs) { 75 | this.jvmArgs = Arrays.asList(extraArgs); 76 | } 77 | 78 | String getClasspath() { 79 | if (JavaVersion.getJavaVersion().isOlderThan(JavaVersion.NINE)) { 80 | return getClasspathJdk8(); 81 | } 82 | return getClasspathJdk9(); 83 | } 84 | 85 | String getClasspathJdk8() { 86 | StringBuilder builder = new StringBuilder(); 87 | 88 | for (URL url : ((URLClassLoader) getClass().getClassLoader()).getURLs()) { 89 | if (builder.length() > 0) { 90 | builder.append(File.pathSeparator); 91 | } 92 | builder.append(url.toString()); 93 | } 94 | 95 | String resultString = builder.toString(); 96 | logger.info("Result Classpath: " + resultString); 97 | 98 | return resultString; 99 | } 100 | 101 | String getClasspathJdk9() { 102 | String classpath = System.getProperty("java.class.path"); 103 | String[] entries = classpath.split(File.pathSeparator); 104 | URL[] result = new URL[entries.length]; 105 | 106 | for (int i = 0; i < entries.length; i++) { 107 | try { 108 | result[i] = Paths.get(entries[i]).toAbsolutePath().toUri().toURL(); 109 | } catch (MalformedURLException e) { 110 | logger.error(e.getStackTrace().toString()); 111 | } 112 | } 113 | 114 | StringBuilder builder = new StringBuilder(); 115 | 116 | for (int i = 0; i < result.length; i++) { 117 | if (builder.length() > 0) { 118 | builder.append(File.pathSeparator); 119 | } 120 | builder.append(result[i]); 121 | } 122 | 123 | String resultString = builder.toString(); 124 | 125 | logger.info("Result Classpath: " + resultString); 126 | 127 | return resultString; 128 | } 129 | 130 | public void after() throws Exception { 131 | if (started != null && started.isAlive()) { 132 | System.err.println("Stopped " + mainClass + ": " + started.destroyForcibly().waitFor()); 133 | } 134 | } 135 | 136 | public void run() throws Exception { 137 | List args = new ArrayList<>(this.args); 138 | if (jvmArgs != null) { 139 | args.addAll(1, this.jvmArgs); 140 | } 141 | args.add(args.size() - this.length, this.mainClass); 142 | if (progArgs != null) { 143 | args.addAll(progArgs); 144 | } 145 | ProcessBuilder builder = new ProcessBuilder(args); 146 | builder.directory(home); 147 | builder.redirectErrorStream(true); 148 | customize(builder); 149 | if (!"false".equals(System.getProperty("debug", "false"))) { 150 | System.err.println("Running: " + Utils.join(args, " ")); 151 | } 152 | started = builder.start(); 153 | monitor(); 154 | } 155 | 156 | protected void customize(ProcessBuilder builder) { 157 | } 158 | 159 | protected void monitor() throws IOException { 160 | System.out.println(output(started.getInputStream(), "Started")); 161 | } 162 | 163 | protected static String output(InputStream inputStream, String marker) throws IOException { 164 | StringBuilder sb = new StringBuilder(); 165 | BufferedReader br = null; 166 | br = new BufferedReader(new InputStreamReader(inputStream)); 167 | String line = null; 168 | while ((line = br.readLine()) != null && !line.contains(marker)) { 169 | sb.append(line + System.getProperty("line.separator")); 170 | } 171 | if (line != null) { 172 | sb.append(line + System.getProperty("line.separator")); 173 | } 174 | return sb.toString(); 175 | } 176 | 177 | public File getHome() { 178 | return home; 179 | } 180 | } -------------------------------------------------------------------------------- /benchmarks/src/test/java/com/bench/ProcessLauncherStateTest.java: -------------------------------------------------------------------------------- 1 | package com.bench; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | class ProcessLauncherStateTest { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(ProcessLauncherStateTest.class); 12 | 13 | private final String CLASSPATH_PART_RESULT = "spring-boot-aspectj/benchmarks/target/test-classes/"; 14 | 15 | @Test 16 | void testApplication() throws Exception { 17 | ProcessLauncherState processLauncherState = new ProcessLauncherState("target"); 18 | processLauncherState.run(); 19 | processLauncherState.after(); 20 | } 21 | 22 | @Test 23 | void testGetClasspathJdk8() { 24 | ProcessLauncherState processLauncherState = new ProcessLauncherState("", ""); 25 | String classpathName = processLauncherState.getClasspathJdk8(); 26 | 27 | logger.info(classpathName); 28 | } 29 | 30 | @Test 31 | void testGetClasspathJdk9() { 32 | ProcessLauncherState processLauncherState = new ProcessLauncherState("", ""); 33 | String classpathName = processLauncherState.getClasspathJdk9(); 34 | 35 | logger.info(classpathName); 36 | 37 | assertTrue(classpathName.contains(CLASSPATH_PART_RESULT)); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /benchmarks/src/test/java/com/bench/StartupBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.bench; 17 | 18 | import org.junit.platform.commons.annotation.Testable; 19 | import org.openjdk.jmh.annotations.AuxCounters; 20 | import org.openjdk.jmh.annotations.AuxCounters.Type; 21 | import org.openjdk.jmh.annotations.Benchmark; 22 | import org.openjdk.jmh.annotations.BenchmarkMode; 23 | import org.openjdk.jmh.annotations.Fork; 24 | import org.openjdk.jmh.annotations.Level; 25 | import org.openjdk.jmh.annotations.Measurement; 26 | import org.openjdk.jmh.annotations.Mode; 27 | import org.openjdk.jmh.annotations.Param; 28 | import org.openjdk.jmh.annotations.Scope; 29 | import org.openjdk.jmh.annotations.Setup; 30 | import org.openjdk.jmh.annotations.State; 31 | import org.openjdk.jmh.annotations.TearDown; 32 | import org.openjdk.jmh.annotations.Warmup; 33 | 34 | import jmh.mbr.junit5.Microbenchmark; 35 | 36 | @Measurement(iterations = 5, time = 1) 37 | @Warmup(iterations = 1, time = 1) 38 | @Fork(value = 2, warmups = 0) 39 | @BenchmarkMode(Mode.AverageTime) 40 | @Microbenchmark 41 | public class StartupBenchmark { 42 | 43 | private static final String M2_REPOSITORY_ASPECTJWEAVER = "/.m2/repository/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar"; 44 | 45 | @Benchmark 46 | @Testable 47 | public void spring(SpringState state) throws Exception { 48 | state.run(); 49 | } 50 | 51 | @Benchmark 52 | @Testable 53 | public void ltw(ApplicationState state) throws Exception { 54 | state.setProgArgs("--spring.aop.auto=false"); 55 | state.setJvmArgs("-javaagent:" + home() + M2_REPOSITORY_ASPECTJWEAVER); 56 | state.run(); 57 | } 58 | 59 | @Benchmark 60 | @Testable 61 | public void ltw_100(ApplicationState state) throws Exception { 62 | state.setProgArgs("--bench.beans=100", "--spring.aop.auto=false"); 63 | state.setJvmArgs("-javaagent:" + home() + M2_REPOSITORY_ASPECTJWEAVER); 64 | state.run(); 65 | } 66 | 67 | private String home() { 68 | return System.getProperty("user.home"); 69 | } 70 | 71 | @State(Scope.Thread) 72 | @AuxCounters(Type.EVENTS) 73 | public static class SpringState extends ProcessLauncherState { 74 | 75 | public static enum Scale { 76 | v0_10(0, 10), v1_10(1, 10), v1_100(1, 100), v10_50(10, 50), v20_50(20, 50), a0_10(0, 10, true), 77 | a1_10(1, 10, true), a1_100(1, 100, true), a10_50(10, 50, true), a10_100(10, 100, true), 78 | a20_50(20, 50, true); 79 | 80 | private int beans; 81 | private int aspects; 82 | private boolean annotation; 83 | 84 | private Scale(int aspects, int beans) { 85 | this(aspects, beans, false); 86 | } 87 | 88 | private Scale(int aspects, int beans, boolean annotation) { 89 | this.beans = beans; 90 | this.aspects = aspects; 91 | this.annotation = annotation; 92 | } 93 | 94 | public String[] getArgs() { 95 | return new String[] { "--server.port=0", "--bench.aspects=" + aspects, "--bench.beans=" + beans, 96 | "--bench.annotation=" + annotation }; 97 | } 98 | } 99 | 100 | @Param // ("a1_100") 101 | private Scale scale = Scale.v1_10; 102 | 103 | public SpringState() { 104 | super("target"); 105 | } 106 | 107 | @Setup(Level.Trial) 108 | public void start() throws Exception { 109 | setProgArgs(scale.getArgs()); 110 | } 111 | 112 | @TearDown(Level.Invocation) 113 | public void stop() throws Exception { 114 | super.after(); 115 | } 116 | } 117 | 118 | @State(Scope.Thread) 119 | @AuxCounters(Type.EVENTS) 120 | public static class ApplicationState extends ProcessLauncherState { 121 | 122 | public ApplicationState() { 123 | super("target", "--server.port=0"); 124 | } 125 | 126 | @TearDown(Level.Invocation) 127 | public void stop() throws Exception { 128 | super.after(); 129 | } 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /benchmarks/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest(properties="logging.level.org.springframework.aop=TRACE") 7 | public class InterceptorApplicationTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ctw/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | ctw 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ctw 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 1.0.24.RELEASE 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | org.springframework 35 | spring-aop 36 | 37 | 38 | org.aspectj 39 | aspectjrt 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-web 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-configuration-processor 48 | true 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 65 | 66 | org.springframework.boot.experimental 67 | spring-boot-thin-layout 68 | ${thin-jar.version} 69 | 70 | 71 | org.aspectj 72 | aspectjweaver 73 | ${aspectj.version} 74 | 75 | 76 | 77 | 78 | 79 | org.eclipse.m2e 80 | lifecycle-mapping 81 | 1.0.0 82 | 83 | 84 | 85 | 86 | 87 | 88 | com.nickwongdev 89 | 90 | 91 | aspectj-maven-plugin 92 | 93 | 94 | [1.10,) 95 | 96 | 97 | compile 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | org.springframework.boot 113 | spring-boot-maven-plugin 114 | 115 | 116 | com.nickwongdev 117 | aspectj-maven-plugin 118 | 1.12.6 119 | 120 | ${java.version} 121 | ${java.version} 122 | none 123 | ${java.version} 124 | true 125 | 126 | 127 | 128 | 129 | compile 130 | 131 | 132 | 133 | 134 | 135 | org.aspectj 136 | aspectjtools 137 | ${aspectj.version} 138 | 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-deploy-plugin 144 | 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | spring-snapshots 154 | Spring Snapshots 155 | https://repo.spring.io/snapshot 156 | 157 | true 158 | 159 | 160 | 161 | spring-milestones 162 | Spring Milestones 163 | https://repo.spring.io/milestone 164 | 165 | false 166 | 167 | 168 | 169 | 170 | 171 | spring-snapshots 172 | Spring Snapshots 173 | https://repo.spring.io/snapshot 174 | 175 | true 176 | 177 | 178 | 179 | spring-milestones 180 | Spring Milestones 181 | https://repo.spring.io/milestone 182 | 183 | false 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /ctw/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | import org.springframework.context.event.EventListener; 11 | 12 | @Aspect 13 | @ConfigurationProperties("interceptor") 14 | public class Interceptor { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); 17 | 18 | /** 19 | * Message to print on startup 20 | */ 21 | private String message = "Startup"; 22 | 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | 31 | @Around("execution(* *(..)) && !within(com.example.Interceptor)" 32 | + " && (within(org.springframework.context.annotation.Condition+) || within(com.example..*))") 33 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 34 | Object result = joinPoint.proceed(); 35 | logger.debug("AspectJ intercept: " + joinPoint.toShortString() + ": " + result); 36 | return result; 37 | } 38 | 39 | @Around("execution(* *(..)) && within(com.example..*) && !within(com.example.Interceptor+)") 40 | public Object stack(ProceedingJoinPoint joinPoint) throws Throwable { 41 | logger.debug("AspectJ stack: " + joinPoint.toShortString()); 42 | return joinPoint.proceed(); 43 | } 44 | 45 | @EventListener 46 | public void started(ContextRefreshedEvent event) { 47 | logger.debug("AspectJ started: " + message + ": " + event); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /ctw/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.Aspects; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @SpringBootApplication 11 | @RestController 12 | public class InterceptorApplication { 13 | 14 | @RequestMapping("/") 15 | public String home() { 16 | return "Hello World"; 17 | } 18 | 19 | @Bean 20 | public Interceptor interceptor() { 21 | // This will barf at runtime if the weaver isn't working (probably a 22 | // good thing) 23 | return Aspects.aspectOf(Interceptor.class); 24 | } 25 | 26 | public static void main(String[] args) { 27 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ctw/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.aop.auto=false 2 | 3 | logging.level.com.example=DEBUG -------------------------------------------------------------------------------- /ctw/src/main/resources/org/aspectj/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ctw/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class InterceptorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ltw/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | ltw 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | ltw 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.2.4.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 8 26 | 1.0.24.RELEASE 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-actuator 33 | 34 | 35 | org.springframework 36 | spring-aop 37 | 38 | 39 | org.aspectj 40 | aspectjrt 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-web 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-configuration-processor 49 | true 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-test 55 | test 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-maven-plugin 65 | 66 | 67 | ${project.build.directory}/aspectj/aspectjweaver-${aspectj.version}.jar 68 | 69 | 70 | 71 | 72 | org.springframework.boot.experimental 73 | spring-boot-thin-layout 74 | ${thin-jar.version} 75 | 76 | 77 | org.aspectj 78 | aspectjweaver 79 | ${aspectj.version} 80 | 81 | 82 | 83 | 84 | org.apache.maven.plugins 85 | maven-surefire-plugin 86 | 87 | -javaagent:${project.build.directory}/aspectj/aspectjweaver-${aspectj.version}.jar 88 | 89 | 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-maven-plugin 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-deploy-plugin 100 | 101 | true 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-dependency-plugin 107 | 108 | 109 | copy 110 | initialize 111 | 112 | copy 113 | 114 | 115 | 116 | 117 | 118 | 119 | org.aspectj 120 | aspectjweaver 121 | ${aspectj.version} 122 | jar 123 | false 124 | ${project.build.directory}/aspectj 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | spring-snapshots 135 | Spring Snapshots 136 | https://repo.spring.io/snapshot 137 | 138 | true 139 | 140 | 141 | 142 | spring-milestones 143 | Spring Milestones 144 | https://repo.spring.io/milestone 145 | 146 | false 147 | 148 | 149 | 150 | 151 | 152 | spring-snapshots 153 | Spring Snapshots 154 | https://repo.spring.io/snapshot 155 | 156 | true 157 | 158 | 159 | 160 | spring-milestones 161 | Spring Milestones 162 | https://repo.spring.io/milestone 163 | 164 | false 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /ltw/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | import org.springframework.context.event.EventListener; 11 | 12 | @Aspect 13 | @ConfigurationProperties("interceptor") 14 | public class Interceptor { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); 17 | 18 | /** 19 | * Message to print on startup 20 | */ 21 | private String message = "Startup"; 22 | 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | 31 | @Around("execution(* *(..)) && !within(com.example.Interceptor)" 32 | + " && (within(org.springframework.context.annotation.Condition+) || within(com.example..*))") 33 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 34 | Object result = joinPoint.proceed(); 35 | logger.debug("AspectJ intercept: " + joinPoint.toShortString() + ": " + result); 36 | return result; 37 | } 38 | 39 | @Around("execution(* *(..)) && within(com.example..*) && !within(com.example.Interceptor+)") 40 | public Object stack(ProceedingJoinPoint joinPoint) throws Throwable { 41 | logger.debug("AspectJ stack: " + joinPoint.toShortString()); 42 | return joinPoint.proceed(); 43 | } 44 | 45 | @EventListener 46 | public void started(ContextRefreshedEvent event) { 47 | logger.debug("AspectJ started: " + message + ": " + event); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /ltw/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.Aspects; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @SpringBootApplication 11 | @RestController 12 | public class InterceptorApplication { 13 | 14 | @RequestMapping("/") 15 | public String home() { 16 | return "Hello World"; 17 | } 18 | 19 | @Bean 20 | public Interceptor interceptor() { 21 | // This will barf at runtime if the weaver isn't working (probably a 22 | // good thing) 23 | return Aspects.aspectOf(Interceptor.class); 24 | } 25 | 26 | public static void main(String[] args) { 27 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ltw/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.aop.auto=false 2 | 3 | logging.level.com.example=DEBUG -------------------------------------------------------------------------------- /ltw/src/main/resources/org/aspectj/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ltw/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class InterceptorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /multi-ctw/ctw-app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | ctw-app 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ctw-app 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 1.0.24.RELEASE 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | com.example 35 | ctw-aspects 36 | ${project.version} 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-web 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-configuration-processor 45 | true 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-test 51 | test 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-maven-plugin 61 | 62 | 63 | org.springframework.boot.experimental 64 | spring-boot-thin-layout 65 | ${thin-jar.version} 66 | 67 | 68 | 69 | 70 | 71 | org.eclipse.m2e 72 | lifecycle-mapping 73 | 1.0.0 74 | 75 | 76 | 77 | 78 | 79 | 80 | com.nickwongdev 81 | 82 | 83 | aspectj-maven-plugin 84 | 85 | 86 | [1.10,) 87 | 88 | 89 | compile 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | org.springframework.boot 105 | spring-boot-maven-plugin 106 | 107 | 108 | com.nickwongdev 109 | aspectj-maven-plugin 110 | 1.12.6 111 | 112 | ${java.version} 113 | ${java.version} 114 | none 115 | ${java.version} 116 | true 117 | 118 | 119 | com.example 120 | ctw-aspects 121 | 122 | 123 | 124 | 125 | 126 | 127 | compile 128 | 129 | 130 | 131 | 132 | 133 | org.aspectj 134 | aspectjtools 135 | ${aspectj.version} 136 | 137 | 138 | 139 | 140 | org.apache.maven.plugins 141 | maven-deploy-plugin 142 | 143 | true 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | spring-snapshots 152 | Spring Snapshots 153 | https://repo.spring.io/snapshot 154 | 155 | true 156 | 157 | 158 | 159 | spring-milestones 160 | Spring Milestones 161 | https://repo.spring.io/milestone 162 | 163 | false 164 | 165 | 166 | 167 | 168 | 169 | spring-snapshots 170 | Spring Snapshots 171 | https://repo.spring.io/snapshot 172 | 173 | true 174 | 175 | 176 | 177 | spring-milestones 178 | Spring Milestones 179 | https://repo.spring.io/milestone 180 | 181 | false 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /multi-ctw/ctw-app/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.Aspects; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @SpringBootApplication 11 | @RestController 12 | public class InterceptorApplication { 13 | 14 | @RequestMapping("/") 15 | public String home() { 16 | return "Hello World"; 17 | } 18 | 19 | @Bean 20 | public Interceptor interceptor() { 21 | // This will barf at runtime if the weaver isn't working (probably a 22 | // good thing) 23 | return Aspects.aspectOf(Interceptor.class); 24 | } 25 | 26 | public static void main(String[] args) { 27 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /multi-ctw/ctw-app/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.aop.auto=false 2 | 3 | logging.level.com.example=DEBUG -------------------------------------------------------------------------------- /multi-ctw/ctw-app/src/main/resources/org/aspectj/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /multi-ctw/ctw-app/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class InterceptorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /multi-ctw/ctw-aspects/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | ctw-aspects 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ctw-aspects 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 1.0.24.RELEASE 26 | 27 | 28 | 29 | 30 | org.springframework 31 | spring-aop 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter 36 | 37 | 38 | org.aspectj 39 | aspectjrt 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | com.nickwongdev 58 | aspectj-maven-plugin 59 | 1.12.6 60 | 61 | ${java.version} 62 | ${java.version} 63 | none 64 | ${java.version} 65 | true 66 | 67 | 68 | 69 | 70 | compile 71 | 72 | 73 | 74 | 75 | 76 | org.aspectj 77 | aspectjtools 78 | ${aspectj.version} 79 | 80 | 81 | 82 | 83 | org.apache.maven.plugins 84 | maven-deploy-plugin 85 | 86 | true 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | org.eclipse.m2e 95 | lifecycle-mapping 96 | 1.0.0 97 | 98 | 99 | 100 | 101 | 102 | 103 | com.nickwongdev 104 | 105 | 106 | aspectj-maven-plugin 107 | 108 | 109 | [1.10,) 110 | 111 | 112 | compile 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | spring-snapshots 130 | Spring Snapshots 131 | https://repo.spring.io/snapshot 132 | 133 | true 134 | 135 | 136 | 137 | spring-milestones 138 | Spring Milestones 139 | https://repo.spring.io/milestone 140 | 141 | false 142 | 143 | 144 | 145 | 146 | 147 | spring-snapshots 148 | Spring Snapshots 149 | https://repo.spring.io/snapshot 150 | 151 | true 152 | 153 | 154 | 155 | spring-milestones 156 | Spring Milestones 157 | https://repo.spring.io/milestone 158 | 159 | false 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /multi-ctw/ctw-aspects/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | import org.springframework.context.event.EventListener; 11 | 12 | @Aspect 13 | @ConfigurationProperties("interceptor") 14 | public class Interceptor { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); 17 | 18 | /** 19 | * Message to print on startup 20 | */ 21 | private String message = "Startup"; 22 | 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | 31 | @Around("execution(* *(..)) && !within(com.example.Interceptor)" 32 | + " && (within(org.springframework.context.annotation.Condition+) || within(com.example..*))") 33 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 34 | Object result = joinPoint.proceed(); 35 | logger.debug("AspectJ intercept: " + joinPoint.toShortString() + ": " + result); 36 | return result; 37 | } 38 | 39 | @Around("execution(* *(..)) && within(com.example..*) && !within(com.example.Interceptor+)") 40 | public Object stack(ProceedingJoinPoint joinPoint) throws Throwable { 41 | logger.debug("AspectJ stack: " + joinPoint.toShortString()); 42 | return joinPoint.proceed(); 43 | } 44 | 45 | @EventListener 46 | public void started(ContextRefreshedEvent event) { 47 | logger.debug("AspectJ started: " + message + ": " + event); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /multi-ctw/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.4.RELEASE 9 | 10 | 11 | 12 | com.example 13 | multi-ctw 14 | 0.0.1-SNAPSHOT 15 | pom 16 | multi-ctw 17 | 18 | 19 | ctw-aspects 20 | ctw-app 21 | 22 | 23 | 24 | 8 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-deploy-plugin 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | spring-libs-snapshot 42 | http://repo.spring.io/libs-snapshot 43 | 44 | true 45 | 46 | 47 | true 48 | 49 | 50 | 51 | 52 | 53 | 54 | spring-libs-snapshot 55 | http://repo.spring.io/libs-snapshot 56 | 57 | true 58 | 59 | 60 | true 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /multi-ltw/ltw-app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | ltw-app 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | ltw-app 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.2.4.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 8 26 | 1.0.24.RELEASE 27 | 1.0.0-SNAPSHOT 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-actuator 34 | 35 | 36 | com.example 37 | ltw-aspects 38 | ${project.version} 39 | 40 | 41 | com.example 42 | timing 43 | ${timing.version} 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-web 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-configuration-processor 52 | true 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-test 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-maven-plugin 68 | 69 | 70 | org.springframework.boot.experimental 71 | spring-boot-thin-layout 72 | ${thin-jar.version} 73 | 74 | 75 | org.aspectj 76 | aspectjweaver 77 | ${aspectj.version} 78 | 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-surefire-plugin 84 | 85 | -javaagent:${project.build.directory}/aspectj/aspectjweaver-${aspectj.version}.jar 86 | 87 | 88 | 89 | org.codehaus.mojo 90 | aspectj-maven-plugin 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | org.springframework.boot 100 | spring-boot-maven-plugin 101 | 102 | 103 | ${project.build.directory}/aspectj/aspectjweaver-${aspectj.version}.jar 104 | 105 | 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-deploy-plugin 110 | 111 | true 112 | 113 | 114 | 115 | org.apache.maven.plugins 116 | maven-dependency-plugin 117 | 118 | 119 | copy 120 | initialize 121 | 122 | copy 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.aspectj 130 | aspectjweaver 131 | ${aspectj.version} 132 | jar 133 | false 134 | ${project.build.directory}/aspectj 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | spring-snapshots 145 | Spring Snapshots 146 | https://repo.spring.io/snapshot 147 | 148 | true 149 | 150 | 151 | 152 | spring-milestones 153 | Spring Milestones 154 | https://repo.spring.io/milestone 155 | 156 | false 157 | 158 | 159 | 160 | 161 | 162 | spring-snapshots 163 | Spring Snapshots 164 | https://repo.spring.io/snapshot 165 | 166 | true 167 | 168 | 169 | 170 | spring-milestones 171 | Spring Milestones 172 | https://repo.spring.io/milestone 173 | 174 | false 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /multi-ltw/ltw-app/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.Aspects; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @SpringBootApplication 11 | @RestController 12 | public class InterceptorApplication { 13 | 14 | @RequestMapping("/") 15 | public String home() { 16 | return "Hello World"; 17 | } 18 | 19 | @Bean 20 | public Interceptor interceptor() { 21 | // This will barf at runtime if the weaver isn't working (probably a 22 | // good thing) 23 | return Aspects.aspectOf(Interceptor.class); 24 | } 25 | 26 | public static void main(String[] args) { 27 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /multi-ltw/ltw-app/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.aop.auto=false 2 | 3 | logging.level.com.example=DEBUG -------------------------------------------------------------------------------- /multi-ltw/ltw-app/src/main/resources/org/aspectj/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /multi-ltw/ltw-app/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class InterceptorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /multi-ltw/ltw-aspects/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | ltw-aspects 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ltw-aspects 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 1.0.24.RELEASE 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter 32 | 33 | 34 | org.springframework 35 | spring-aop 36 | 37 | 38 | org.aspectj 39 | aspectjrt 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.apache.maven.plugins 58 | maven-deploy-plugin 59 | 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | spring-snapshots 69 | Spring Snapshots 70 | https://repo.spring.io/snapshot 71 | 72 | true 73 | 74 | 75 | 76 | spring-milestones 77 | Spring Milestones 78 | https://repo.spring.io/milestone 79 | 80 | false 81 | 82 | 83 | 84 | 85 | 86 | spring-snapshots 87 | Spring Snapshots 88 | https://repo.spring.io/snapshot 89 | 90 | true 91 | 92 | 93 | 94 | spring-milestones 95 | Spring Milestones 96 | https://repo.spring.io/milestone 97 | 98 | false 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /multi-ltw/ltw-aspects/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | import org.springframework.context.event.EventListener; 11 | 12 | @Aspect 13 | @ConfigurationProperties("interceptor") 14 | public class Interceptor { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); 17 | 18 | /** 19 | * Message to print on startup 20 | */ 21 | private String message = "Startup"; 22 | 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | 31 | @Around("execution(* *(..)) && !within(com.example.Interceptor)" 32 | + " && (within(org.springframework.context.annotation.Condition+) || within(com.example..*))") 33 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 34 | Object result = joinPoint.proceed(); 35 | logger.debug("AspectJ intercept: " + joinPoint.toShortString() + ": " + result); 36 | return result; 37 | } 38 | 39 | @Around("execution(* *(..)) && within(com.example..*) && !within(com.example.Interceptor+)") 40 | public Object stack(ProceedingJoinPoint joinPoint) throws Throwable { 41 | logger.debug("AspectJ stack: " + joinPoint.toShortString()); 42 | return joinPoint.proceed(); 43 | } 44 | 45 | @EventListener 46 | public void started(ContextRefreshedEvent event) { 47 | logger.debug("AspectJ started: " + message + ": " + event); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /multi-ltw/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.4.RELEASE 9 | 10 | 11 | 12 | com.example 13 | multi-ltw 14 | 0.0.1-SNAPSHOT 15 | pom 16 | multi-ltw 17 | 18 | 19 | ltw-aspects 20 | ltw-app 21 | 22 | 23 | 24 | 8 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-deploy-plugin 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | spring-libs-snapshot 42 | http://repo.spring.io/libs-snapshot 43 | 44 | true 45 | 46 | 47 | true 48 | 49 | 50 | 51 | 52 | 53 | 54 | spring-libs-snapshot 55 | http://repo.spring.io/libs-snapshot 56 | 57 | true 58 | 59 | 60 | true 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | echo "Running version check" 230 | VERSION=$( sed '\!//' -e 's!.*$!!' ) 231 | echo "The found version is [${VERSION}]" 232 | 233 | if echo $VERSION | egrep -q 'M|RC'; then 234 | echo Activating \"milestone\" profile for version=\"$VERSION\" 235 | echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pmilestone" 236 | else 237 | echo Deactivating \"milestone\" profile for version=\"$VERSION\" 238 | echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//') 239 | fi 240 | 241 | if echo $VERSION | egrep -q 'RELEASE'; then 242 | echo Activating \"central\" profile for version=\"$VERSION\" 243 | echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pcentral" 244 | else 245 | echo Deactivating \"central\" profile for version=\"$VERSION\" 246 | echo $MAVEN_ARGS | grep -q central && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pcentral//') 247 | fi 248 | 249 | exec "$JAVACMD" \ 250 | $MAVEN_OPTS \ 251 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 252 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 253 | ${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@" 254 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% 146 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.4.RELEASE 9 | 10 | 11 | com.example 12 | spring-boot-aspectj 13 | 0.0.1-SNAPSHOT 14 | pom 15 | spring-boot-aspectj 16 | 17 | 18 | timing 19 | spring 20 | ltw 21 | ctw 22 | multi-ltw 23 | multi-ctw 24 | benchmarks 25 | 26 | 27 | 28 | 11 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-deploy-plugin 36 | 37 | true 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | spring-libs-snapshot 46 | http://repo.spring.io/libs-snapshot 47 | 48 | true 49 | 50 | 51 | true 52 | 53 | 54 | 55 | 56 | 57 | 58 | spring-libs-snapshot 59 | http://repo.spring.io/libs-snapshot 60 | 61 | true 62 | 63 | 64 | true 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | spring 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | spring 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 1.0.24.RELEASE 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-aop 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-maven-plugin 60 | 61 | 62 | org.springframework.boot.experimental 63 | spring-boot-thin-layout 64 | ${thin-jar.version} 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-maven-plugin 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-deploy-plugin 78 | 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | spring-snapshots 88 | Spring Snapshots 89 | https://repo.spring.io/snapshot 90 | 91 | true 92 | 93 | 94 | 95 | spring-milestones 96 | Spring Milestones 97 | https://repo.spring.io/milestone 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | spring-snapshots 106 | Spring Snapshots 107 | https://repo.spring.io/snapshot 108 | 109 | true 110 | 111 | 112 | 113 | spring-milestones 114 | Spring Milestones 115 | https://repo.spring.io/milestone 116 | 117 | false 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /spring/src/main/java/com/example/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | import org.springframework.context.event.EventListener; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Aspect 14 | @ConfigurationProperties("interceptor") 15 | @Component 16 | public class Interceptor { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(Interceptor.class); 19 | 20 | /** 21 | * Message to print on startup 22 | */ 23 | private String message = "Startup"; 24 | 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | 33 | @Around("execution(* *.*(..)) && within(com.example..*)") 34 | public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable { 35 | Object result = joinPoint.proceed(); 36 | logger.debug("AspectJ intercept: " + joinPoint.toShortString() + ": " + result); 37 | return result; 38 | } 39 | 40 | @Around("execution(* *.*(..)) && within(com.example..*)") 41 | public Object another(ProceedingJoinPoint joinPoint) throws Throwable { 42 | Object result = joinPoint.proceed(); 43 | logger.debug("AspectJ another: " + joinPoint.toShortString() + ": " + result); 44 | return result; 45 | } 46 | 47 | @EventListener 48 | public void started(ContextRefreshedEvent event) { 49 | logger.debug("AspectJ started: " + message + ": " + event); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /spring/src/main/java/com/example/InterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @SpringBootApplication 9 | @RestController 10 | public class InterceptorApplication { 11 | 12 | @RequestMapping("/") 13 | public String home() { 14 | return "Hello World"; 15 | } 16 | 17 | public static void main(String[] args) { 18 | new SpringApplicationBuilder(InterceptorApplication.class).run(args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /spring/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.com.example=DEBUG -------------------------------------------------------------------------------- /spring/src/test/java/com/example/InterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest(properties = { "logging.level.org.springframework.aop=TRACE", "logging.level.com.example=DEBUG" }) 10 | public class InterceptorApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /timing/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /timing/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsyer/spring-boot-aspectj/79f5f76a398657bd846045b33621375f43c24aef/timing/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /timing/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip 2 | -------------------------------------------------------------------------------- /timing/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /timing/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /timing/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | timing 8 | 1.0.0-SNAPSHOT 9 | jar 10 | 11 | timing 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.2.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | org.aspectj 34 | aspectjrt 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | 44 | 45 | https://github.com/dsyer/spring-boot-aspectj 46 | 47 | spring-docs 48 | scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-boot/docs/${project.artifactId}/${project.version} 49 | 50 | 51 | sonatype-nexus-staging 52 | Nexus Release Repository 53 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 54 | 55 | 56 | repo.spring.io 57 | Spring Snapshot Repository 58 | https://repo.spring.io/libs-snapshot-local 59 | 60 | 61 | 62 | 63 | milestone 64 | 65 | 66 | repo.spring.io 67 | Spring Milestone Repository 68 | https://repo.spring.io/libs-milestone-local 69 | 70 | 71 | 72 | 73 | central 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-gpg-plugin 79 | 80 | 81 | sign-artifacts 82 | verify 83 | 84 | sign 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /timing/src/main/java/org/springframework/boot/aspects/AspectConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.boot.aspects; 17 | 18 | import org.aspectj.lang.Aspects; 19 | 20 | import org.springframework.boot.autoconfigure.condition.ConditionOutcome; 21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 22 | import org.springframework.boot.autoconfigure.condition.SpringBootCondition; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.ConditionContext; 25 | import org.springframework.context.annotation.Conditional; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.core.type.AnnotatedTypeMetadata; 28 | 29 | /** 30 | * @author Dave Syer 31 | * 32 | */ 33 | @Configuration 34 | public class AspectConfiguration { 35 | 36 | @Bean 37 | @Conditional(AspectsCondition.class) 38 | @ConditionalOnClass(name = "org.aspectj.lang.Aspects") 39 | public TimingInterceptor timingInterceptor() { 40 | return Aspects.aspectOf(TimingInterceptor.class); 41 | } 42 | 43 | private static class AspectsCondition extends SpringBootCondition { 44 | 45 | @Override 46 | public ConditionOutcome getMatchOutcome(ConditionContext context, 47 | AnnotatedTypeMetadata metadata) { 48 | if (Aspects.hasAspect(TimingInterceptor.class)) { 49 | return ConditionOutcome.match("AspectJ weaving"); 50 | } 51 | return ConditionOutcome.noMatch("AspectJ not weaving"); 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /timing/src/main/java/org/springframework/boot/aspects/TimingInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.boot.aspects; 17 | 18 | import org.aspectj.lang.ProceedingJoinPoint; 19 | import org.aspectj.lang.annotation.Around; 20 | import org.aspectj.lang.annotation.Aspect; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.context.event.ContextRefreshedEvent; 24 | import org.springframework.context.event.EventListener; 25 | import org.springframework.util.StopWatch; 26 | 27 | /** 28 | * @author Dave Syer 29 | * 30 | */ 31 | @Aspect 32 | public class TimingInterceptor { 33 | 34 | private static final Logger logger = LoggerFactory.getLogger(TimingInterceptor.class); 35 | 36 | private StopWatch bind = new StopWatch("bind"); 37 | 38 | private StopWatch init = new StopWatch("init"); 39 | 40 | private StopWatch app = new StopWatch("app"); 41 | 42 | private int level = 0; 43 | 44 | @Around("execution(private * org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(Object, String, ..)) && args(bean,..)") 45 | public Object bind(ProceedingJoinPoint joinPoint, Object bean) throws Throwable { 46 | bind.start(); 47 | Object result = joinPoint.proceed(); 48 | bind.stop(); 49 | logger.debug("Bind,," + bean.getClass().getName() + ": " + bind.getLastTaskTimeMillis()); 50 | return result; 51 | } 52 | 53 | @Around("execution(* org.springframework.beans.factory.config.BeanPostProcessor+.*(Object, String)) && args(bean,..)") 54 | public Object post(ProceedingJoinPoint joinPoint, Object bean) throws Throwable { 55 | long t0 = System.nanoTime(); 56 | Object result = joinPoint.proceed(); 57 | long t1 = System.nanoTime(); 58 | logger.info("Post," + joinPoint.getSignature().getDeclaringType().getSimpleName() 59 | + "." + joinPoint.getSignature().getName() + "," 60 | + bean.getClass().getName() + "," + (t1 - t0) / 1000000.); 61 | return result; 62 | } 63 | 64 | @Around("execution(* org.springframework.boot.SpringApplication+.*(..))") 65 | public Object initializer(ProceedingJoinPoint joinPoint) throws Throwable { 66 | String task = app.currentTaskName(); 67 | if (task != null) { 68 | app.stop(); 69 | } 70 | long t0 = System.nanoTime(); 71 | level++; 72 | app.start(joinPoint.getSignature().getName()); 73 | Object result = joinPoint.proceed(); 74 | long t1 = System.nanoTime(); 75 | app.stop(); 76 | if (task != null) { 77 | app.start(task); 78 | } 79 | logger.info("App," + level + "," + joinPoint.getSignature().getName() + "," 80 | + (t1 - t0) / 1000000.); 81 | level--; 82 | return result; 83 | } 84 | 85 | @Around("execution(* org.springframework.web.reactive.DispatcherHandler+.initStrategies(..))") 86 | public Object initStrategies(ProceedingJoinPoint joinPoint) throws Throwable { 87 | long t0 = System.nanoTime(); 88 | Object result = joinPoint.proceed(); 89 | long t1 = System.nanoTime(); 90 | logger.info("Strategies," 91 | + joinPoint.getSignature().getDeclaringType().getSimpleName() + "." 92 | + joinPoint.getSignature().getName() + "," + (t1 - t0) / 1000000.); 93 | return result; 94 | } 95 | 96 | @Around("execution(* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory+.initializeBean(String, Object, ..)) && args(name,bean,..)") 97 | public Object init(ProceedingJoinPoint joinPoint, String name, Object bean) throws Throwable { 98 | String task = init.currentTaskName(); 99 | if (task != null) { 100 | init.stop(); 101 | } 102 | init.start(name); 103 | int count0 = init.getTaskCount(); 104 | long t0 = System.nanoTime(); 105 | Object result = joinPoint.proceed(); 106 | long t1 = System.nanoTime(); 107 | int count1 = init.getTaskCount(); 108 | init.stop(); 109 | if (task != null) { 110 | init.start(task); 111 | } 112 | else { 113 | logger.info( 114 | "Init,," + bean.getClass().getName() + "," + (t1 - t0) / 1000000.); 115 | logger.info("Count,," + bean.getClass().getName() + "," + (count1 - count0)); 116 | } 117 | return result; 118 | } 119 | 120 | @EventListener 121 | public void started(ContextRefreshedEvent event) { 122 | logger.debug("Total bind: " + bind.getTotalTimeMillis()); 123 | logger.debug("Total init: " + init.getTotalTimeMillis()); 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /timing/src/main/resources/META-INF/aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /timing/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | org.springframework.boot.aspects.AspectConfiguration -------------------------------------------------------------------------------- /timing/src/test/java/org/springframework/boot/aspects/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package org.springframework.boot.aspects; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /timing/src/test/java/org/springframework/boot/aspects/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.boot.aspects; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------