The simplest HelloWorld example of aspectJ
This is the introduction of aspectJ. What's the difference between aspectJ and aop? aspectJ can also implement aop functions. aop generally refers to spring aop, which is a set of annotations such as @ Aspect/@Pointcut/@Before/@Around. The implementation principle is dynamic agent. aspectJ is more efficient in embedding notifications at the compiler level
As you can guess, aspectJ is similar to lombok in that the compiler helps you "write" the notification code (the logic of printing the log after interception, called "notification"). Although aspectJ is efficient, it needs a special compiler, so it is not as convenient as aop. aop is less efficient than aspectJ, but it can also be accepted. So I have never seen aspectJ used in my work for many years
Introduction and comparison of spring aop
Here is an excerpt from https://www.jianshu.com/p/872d3dbdc2ca
Spring AOP | AspectJ |
---|---|
Implemented in pure Java | Extended implementation using Java programming language |
No separate compilation process is required | AspectJ compiler (ajc) is required unless LTW is set |
Run time weaving only | Runtime weaving is not available. Support compile time, post compile and load time weaving |
Weak function - only method level weaving is supported | More powerful - can weave fields, methods, constructors, static initializers, final classes / methods, etc. |
Can only be implemented on bean s managed by Spring containers | Can be implemented on all domain objects |
Only method execution pointcuts are supported | Support all entry points |
Delegates are created by target objects and facets are applied to these delegates | Before executing the application (at runtime), all aspects are woven directly into the code |
Much slower than AspectJ | Better performance |
Easy to learn and apply | More complex than Spring AOP |
HelloWorld of aspectj
Writing examples to experience aspectj is a good way to help understand things.
Here are the helloworld new steps of aspectJ. I built a project with web in springboot, because this project can use the web more easily.
Note during testing: sometimes you don't know if it's a cache. Running the test main method will find that the interception doesn't take effect. You need to recompile cmd+f9 to take effect
Steps:
- Build a project for testing
In IDEA, click file - > New - > Project ->Spring initializer - > create a project including spring web all the way (the detailed steps are omitted, do not follow this operation strictly, you can use maven to build a project) - Modify the compiler of IDEA
Only modify the compiler of the current project without affecting the global: in IntelliJ idea - > preferences ->Build, execution, deployment - > compiler - > java compiler (this modification only affects the current project, so you can modify it safely!)
Change the compiler Javac to Ajc, and specify the location of aspectjtools.jar (see the following for the obtaining method)
-
How to get aspectjtools.jar
-
Download directly to the maven central warehouse page: search for aspectjtools and download the latest version. Version 1.9.5 Download , and then save it in your own directory, and reference the path
-
Or, introduce GAV into pom.xml of the project, download it in the local maven warehouse, find the path of the jar package, and reference it. The GAV introduced in the project to download the jar package can be deleted (it's ok if it's not deleted, but it's customary to delete the unneeded GAV)
<!-- aspectjtools: Download what you need jar You can delete this after the package GAV --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.5</version> </dependency>
-
-
Introduce the required jar package, add the following GAV in pom.xml, which is a necessary jar
<!-- aspectj --> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.4</version> </dependency>
If this jar package is missing, an exception not found by the class will be thrown at runtime
Exception in thread "main" java.lang.NoClassDefFoundError: org/aspectj/lang/NoAspectBoundException at com.wyf.test.aopaspectjspring.example01.HelloWorld.main(HelloWorld.java:20) Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.NoAspectBoundException at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more
Add: it can be found that org.aspectj.lang.NoAspectBoundException is in the jar package of aspectj:aspectj:1.5.4 that we introduced.
PS: actually, the jar of aspectjtools also has this class, so it's OK to choose one of the two gavs of aspectjtools and aspectjrt, or even keep one. However, we still keep aspectjrt to remove GAV of aspectjtools
-
Create a new Aspect for intercepting; a new HelloWorld class for writing intercepted methods and main methods for testing
- This aspect class is a file with an. AJ extension, such as LogAspectJ.aj. It needs to be compiled by the Acj compiler. The compiled file is also a clas file, such as LogAspectJ.class
package com.wyf.test.aopaspectjspring.example01; /** * * @author Stone * @version V1.0.0 * @date 2020/2/19 */ public aspect LogAspectJ { void around(): call(void HelloWorld.sayHello()) { System.out.println("Log before..."); proceed(); System.out.println("After log..."); } }
package com.wyf.test.aopaspectjspring.example01; /** * @author Stone * @version V1.0.0 * @date 2020/2/19 */ public class HelloWorld { public void sayHello() { System.out.println("Hello, AspectJ!"); } /** * Test method: run time discovery can be intercepted * * @param args */ public static void main(String[] args) { HelloWorld helloWorld = new HelloWorld(); helloWorld.sayHello(); } }
-
Run HelloWorld's main method and find the print
Before logging... Hello, AspectJ! After log...
(if you don't print like this, check in two aspects. First, check file - > settings to see if it is the Adj compiler. IDEA seems to have a bug. If you change pom.xml a little, you will call back the original Java C compiler. Second, you may change the cache, such as sometimes changing System.out.println("before log..."); for example, changing the printed string to System.out.println("before log 222..."); It will be found that it doesn't work. In this case, use cmd+f9 to trigger compilation and then run.)
appendix
Decompile HelloWorld and LogAspectJ to get the following source code (decompile with IDEA) "
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.wyf.test.aopaspectjspring.example01; import org.aspectj.lang.NoAspectBoundException; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.runtime.internal.AroundClosure; @Aspect public class LogAspectJ { static { try { ajc$postClinit(); } catch (Throwable var1) { ajc$initFailureCause = var1; } } public LogAspectJ() { } @Around( value = "call(void HelloWorld.sayHello())", argNames = "ajc$aroundClosure" ) public void ajc$around$com_wyf_test_aopaspectjspring_example01_LogAspectJ$1$8852f95(AroundClosure ajc$aroundClosure) { System.out.println("Log before..."); ajc$around$com_wyf_test_aopaspectjspring_example01_LogAspectJ$1$8852f95proceed(ajc$aroundClosure); System.out.println("After log..."); } public static LogAspectJ aspectOf() { if (ajc$perSingletonInstance == null) { throw new NoAspectBoundException("com_wyf_test_aopaspectjspring_example01_LogAspectJ", ajc$initFailureCause); } else { return ajc$perSingletonInstance; } } public static boolean hasAspect() { return ajc$perSingletonInstance != null; } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.wyf.test.aopaspectjspring.example01; import org.aspectj.lang.NoAspectBoundException; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.runtime.internal.AroundClosure; @Aspect public class LogAspectJ { static { try { ajc$postClinit(); } catch (Throwable var1) { ajc$initFailureCause = var1; } } public LogAspectJ() { } @Around( value = "call(void HelloWorld.sayHello())", argNames = "ajc$aroundClosure" ) public void ajc$around$com_wyf_test_aopaspectjspring_example01_LogAspectJ$1$8852f95(AroundClosure ajc$aroundClosure) { System.out.println("Log before..."); ajc$around$com_wyf_test_aopaspectjspring_example01_LogAspectJ$1$8852f95proceed(ajc$aroundClosure); System.out.println("After log..."); } public static LogAspectJ aspectOf() { if (ajc$perSingletonInstance == null) { throw new NoAspectBoundException("com_wyf_test_aopaspectjspring_example01_LogAspectJ", ajc$initFailureCause); } else { return ajc$perSingletonInstance; } } public static boolean hasAspect() { return ajc$perSingletonInstance != null; } }