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