1 Introduction
AOP, that is, aspect-oriented programming is a very common technology, especially in Java Web development. The most popular AOP frameworks are Spring AOP and AspectJ respectively.
2 Spring AOP vs AspectJ
Spring AOP is implemented based on Spring IoC, which solves most of the common needs, but it is not a complete AOP solution. For objects that are not managed by the Spring container, it has nothing to do. AspectJ aims to provide a complete AOP solution, so it will be more complicated.
2.1 Weaving method
The weaving methods of the two are very different, which is also their essential difference, and they implement agents in different ways.
AspectJ is woven in before running and is divided into three categories:
- compile time weaving
- weaving after compilation
- weave on load
Therefore, support from the AspectJ compiler (ajc) is required.
Spring AOP is woven at runtime and mainly uses two technologies: JDK dynamic proxy and CGLIB proxy. Use JDK Proxy for interfaces, and CGLIB for inherited ones.
2.2 Joinpoints
Because of the difference in weaving methods, the Joinpoints supported by the two are also different. Methods like final and static methods cannot be changed through dynamic proxies, so Spring AOP cannot support them. But AspectJ weaves the actual code directly before running, so the function will be much more powerful.
Joinpoint | Spring AOP Supported | AspectJ Supported |
---|---|---|
Method Call | No | Yes |
Method Execution | Yes | Yes |
Constructor Call | No | Yes |
Constructor Execution | No | Yes |
Static initializer execution | No | Yes |
Object initialization | No | Yes |
Field reference | No | Yes |
Field assignment | No | Yes |
Handler execution | No | Yes |
Advice execution | No | Yes |
2.3 Performance
Compilation and weaving are much faster than runtime weaving. Spring AOP uses proxy mode to create corresponding proxy classes at runtime, which is not as efficient as AspectJ.
3 Spring Boot uses AspectJ
Because AspectJ is more powerful and will be used more in projects, so here we only introduce its integration with Spring Boot.
3.1 Import dependencies
Introduce the following dependencies, and add Lombok and aspectj on the basis of Spring Boot:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <scope>provided</scope> </dependency> </dependencies>
3.2 AOP object
In order to verify the function of AOP, we add a TestController, which has a method for processing Get requests, and calls private member methods and static methods at the same time:
@RestController @RequestMapping("/test") @Slf4j public class TestController { @GetMapping("/hello") public String hello() { log.info("---hello() start---"); test(); staticTest(); log.info("---hello() end---"); return "Hello, pkslow."; } private void test() { log.info("------test() start---"); log.info("test"); log.info("------test() end---"); } private static void staticTest() { log.info("------staticTest() start---"); log.info("staticTest"); log.info("------staticTest() end---"); } }
3.3 Configuring Aspect
The configuration aspects are as follows:
@Aspect @Component @Slf4j //@EnableAspectJAutoProxy public class ControllerAspect { @Pointcut("execution(* com.pkslow.springboot.controller..*.*(..))") private void testControllerPointcut() { } @Before("testControllerPointcut()") public void doBefore(JoinPoint joinPoint){ log.info("------pkslow aop doBefore start------"); String method = joinPoint. getSignature(). getName(); String declaringTypeName = joinPoint. getSignature(). getDeclaringTypeName(); log.info("Method: {}.{}" ,declaringTypeName, method); log.info("------pkslow aop doBefore end------"); } @Around("testControllerPointcut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { log.info("------pkslow aop doAround start------"); long start = System. nanoTime(); Object obj = joinPoint. proceed(); long end = System. nanoTime(); log.info("Execution Time: " + (end - start) + " ns"); log.info("------pkslow aop doAround end------"); return obj; } }
@Pointcut
defines which classes and methods will be captured and proxied. Here, all methods under the controller are configured.
And @Before
and @Around
define some processing logic. @Before
is to print the method name, and @Around
is to make a timing.
Note: It is not necessary to configure @EnableAspectJAutoProxy
.
3.4 maven plugin
Because it needs to weave code at compile time, it needs the support of maven plugin: GitHub – mojohaus/aspectj-maven-plugin
Just configure the pom.xml file.
Then execute the command to package:
mvn clean package
At this time, some weaving information will be displayed, roughly as follows:
[INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:14) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController. java:14) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:28) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:28) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
If you see the above information, it means that the code has been successfully woven. For details, you can check the generated class file.
It can be seen that many codes are not written by us, but are woven into the generated code.
3.5 Implementation and Testing
After the compilation is successful, we execute the code. If it is executed through IDEA, there is no need to build before running, because the package has been built through maven. It may not be possible to weave through IDEA’s built-in compiler build. Or choose ajc as compiler. For details, please refer to: IDEA starts Springboot but AOP fails
Access is as follows:
GET http://localhost:8080/test/hello
The log is as follows, and the AOP function is successfully implemented:
3.6 Some errors encountered
An error was encountered:
ajc Syntax error, annotations are only available if source level is 1.5 or greater
Plugins need to be configured:
<complianceLevel>${java.version}</complianceLevel> <source>${java.version}</source> <target>${java.version}</target>
You may also encounter an error that Lombok cannot be recognized. The configuration is as follows to solve this problem:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>${java.version}</complianceLevel> <source>${java.version}</source> <target>${java.version}</target> <proc>none</proc> <showWeaveInfo>true</showWeaveInfo> <forceAjcCompile>true</forceAjcCompile> <sources/> <weave Directories> <weaveDirectory>${project.build.directory}/classes</weaveDirectory> </weaveDirectories> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin>
4 Summary
There are many AOP scene applications, and it still needs to be mastered.
Please see GitHub for the code: GitHub – LarryDpk/pkslow-samples: samples for www.pkslow.com: Java, Spring Boot, Spring Cloud, Docker, Kubernetes, Cloud, Big Data
Tags: Java