Spring AOP this 失效解决方案,使用 self() 代替

众所周知,在 Spring 的 bean 中使用 this 引用,会导致 AOP 切面失效,那我们就不用 this,使用 self() 代替


SpringUtils.java
package com.xxx.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

}

SelfRefBean.java
package com.xxx.self;

import com.xxx.util.SpringUtils;

public interface SelfRefBean<T extends SelfRefBean<T>> {

    default T self() {
        SelfRefBean<?> bean = SpringUtils.getBean(this.getClass());
        return (T) bean;
    }

}

TestService.java,实现 SelfRefBean 接口即可,泛型类传递自身
package com.xxx.service;

import com.xxx.self.SelfRefBean;
import org.springframework.stereotype.Service;

@Service
public class TestService implements SelfRefBean<TestService> {

    public void test1() {
        System.out.println("test1");
        self().test2();
    }

    public void test2() {
        System.out.println("test2");
    }

}

TestController.java
package com.xxx.controller;

import com.xxx.service.TestService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class TestController {

    @Resource
    private TestService testService;

    @GetMapping("/test")
    public void test() {
        testService.test1();
    }

}

TestAop.java
package com.xxx.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TestAop {

    /**
     * 切入点表达式
     */
    @Pointcut("execution(* com.xxx.service.*Service.*(..))")
    public void logPointCut() {
    }

    /**
     * 前置通知
     */
    @Before("logPointCut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知:" + joinPoint.getTarget());
    }

}

 

执行 curl

curl http://localhost:8080/test

 

console 打印:

前置通知:void com.xxx.service.TestService.test1()
test1
前置通知:void com.xxx.service.TestService.test2()
test2

 

  

posted @ 2024-01-16 15:35  Nihaorz  阅读(204)  评论(0编辑  收藏  举报