During development, I encountered such a problem. The project uses the springboot framework. The task in the project is implemented based on quartz. There is a BaseTask code that implements the quartz Job interface. The key code is as follows:
import ; import ; import ; public abstract class BaseTask implements Job { @Override public void execute(JobExecutionContext context) { // do something before... doTask(taskDto); // do something after... } public abstract void doTask(TaskDTO taskDto); }
All tasks in the project will inherit this BaseTask and override the doTask method as follows:
public class MyTask extends BaseTask { @Override public void doTask(TaskDTO taskDto) { // Implement your specific task logic here ("Execute MyTask doTask method"); } }
At this time, the business you do will involve many similar data synchronization and many tasks, and all of them need to be done as follows:
1. Implement concurrent lock control
2. Read the last synchronization time for incremental synchronization operation
3. Insert taskRecord record, etc.
These codes will be extremely redundant and duplicated, so I want to use the idea of AOP and use annotations to abstractly integrate these operations, so I started to do it:
1. Introduce springboot's AOP dependency
<dependency> <groupId></groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. Write annotations:
@Target() @Retention() public @interface TaskRecord { }
3. Use @Aspect to write facelifts
import ; import ; import ; import ; import ; @Aspect @Component public class TaskAspect { @Pointcut("execution(* .*.doTask(..)) && @annotation(TaskRecord)") public void pointcut() {} @Before("pointcut()") public void before(JoinPoint joinPoint) { Object[] args = (); // Get the parameters of the method ("Method Parameters: " + args[0]); } }
4. Add annotations to the MyTask class method
public class MyTask extends BaseTask { @Override @TaskRecord public void doTask(TaskDTO taskDto) { // Implement your specific task logic here ("Execute MyTask doTask method"); } }
After some operation, I thought to myself: I'm the best in the world in the cv code, and there is definitely no problem. Break the debug point debugging, find that the problem occurs, and you can't get into the @Before method at all
So I checked the problem, Baidu chatgpt asked n²+1 day and tried the following methods such as:
1. Load the bean into spring container with MyTask, BaseTask plus @Component
2. Add @EnableAspectJAutoProxy annotation to the startup class (actual SpringBoot automatically configures AOP by default)
3. Is Lenovo related to CGLIB or JDK dynamic proxy?
A series of operations were found to be defeated repeatedly, so I put it aside for several days. Today I tried it on a whim, changed my mind to think about it, and checked several scenes of AOP failure. The summary is as follows:
1. Internal method calls: AOP usually does not intercept method calls inside the same class. If a proxy method calls another proxy method, only the externally called method will trigger the AOP.
Configuration issue: AOP point-cutting is not configured correctly, and point-cutting expressions may not be applied to the target bean correctly.
3. Directly instantiate the object: If an object instance is created directly using the new keyword, AOP will not be able to intercept the method calls of this object. You need to obtain objects through Spring containers and let Spring be responsible for instantiating beans in order for AOP to take effect.
Um? It seems to have some idea, which fits the situation of 1, so I wrote a request and added annotations to a controller, and found that I could enter, but if I write an internal method and add annotations to the internal method, the requested method will be invalid, as follows:
That's OK
@RequestMapping("/test") @ResponseBody @TaskRecord public String test(@RequestBody TestRequest request) { test1(request); return "Execution was successful!"; }
That's not OK
@RequestMapping("/test") @ResponseBody public String test(@RequestBody TestRequest request) { test1(request); return "Execution was successful!"; } @TaskRecord public void test1(TestRequest request) { (()); }
So the idea is that when executing the internal doTask method, it cannot be called directly. It needs to be called through the proxy class to make the AOP section take effect. The modification is as follows:
1. Added interface
public interface JobCommonService { void doTaskNew(TaskDTO taskDTO) throws Exception; }
Renovation, do not call doTask directly
import ; import ; import ; public abstract class BaseTask implements Job { @Override public void execute(JobExecutionContext context) { // do something before... // This is a self-built spring container tool class that can obtain beans in the container JobCommonService jobService = (); (taskDTO); // do something after... } public abstract void doTask(TaskDTO taskDto); }
3. Specific task transformation, implement the JobCommon interface rewrite doTaskNew method
@Component public class MyTask extends BaseTask implements JobCommonService{ @Override public void doTask(TaskDTO taskDto) { return; } @Override @TaskRecord public void doTaskNew(TaskDTO taskDTO) { // do something... return; } }
After finishing work, I successfully entered the @Before method. Close all the query windows below and you can perform other operations happily!
This is the article about the troubleshooting and solving SpringBoot AOP annotation failure problem (calling internal methods). For more relevant SpringBoot AOP annotation failure content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!