SpringBoot中創(chuàng)建的AOP不生效的原因及解決
SpringBoot 創(chuàng)建AOP不生效的原因
最近在學(xué)習(xí)SpringBoot,今天學(xué)習(xí)了Aop的注冊方式,原理很簡單,配置也很簡單,但是我注冊了切面之后切面一直不生效,是為什么呢?查了好久的資料終于發(fā)現(xiàn)了原因,可以看下圖我的切面注冊類并沒有問題

然后在網(wǎng)上偶然看到可能是主程序掃描的原因,才發(fā)現(xiàn)了原因,可以看到我的顯示方式本來是flat的,那樣的話就很難找出原因了

修改為hirerchical就可以很清楚的看出問題

可以看出,我的主程序和切面類并不在一個包中,那么主程序掃描不到切面類,自然就不會注冊切面了,最簡單的解決方式就是在主程序中添加一個注解@ComponentScan

那么我們就能對springboot有更深入的認(rèn)識,其實他相對于ssm所有的簡化步驟關(guān)鍵在于主程序,他起到了一個封裝加載的步驟,不主動聲明的情況下他會掃描和自己在同一個包下面的所有類,并根據(jù)注解自動注冊,那么以后寫項目時最好的方式就是將主程序放在主包下,然后所有的這些類都放在子包中即可
SpringBoot aop無效的情況
項目結(jié)構(gòu)

package com.example.demo.inter;
public interface CustomerService {
void doSomething1();
void doSomething2();
}
package com.example.demo.inter;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
@Service
public class CustomerServiceImpl implements CustomerService {
@Override
public void doSomething1() {
System.out.println("CustomerServiceImpl.doSomething1()");
doSomething2();
((CustomerService) AopContext.currentProxy()).doSomething2();
}
@Override
public void doSomething2() {
System.out.println("CustomerServiceImpl.doSomething2()");
}
}
package com.example.demo;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class CustomerServiceInterceptor {
@Before("execution(* com.example.demo.inter..*.*(..))")
public void doBefore() {
System.out.println("do some important things before...");
}
}
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy(proxyTargetClass=true, exposeProxy=true)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
package com.example.demo;
import com.example.demo.inter.CustomerService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Autowired
CustomerService customerService;
@Test
public void testAOP() {
customerService.doSomething1();
}
@Test
void contextLoads() {
}
}
運行下testAOP,為啥doSomething2()沒有切面效果,使用AopContext.currentProxy就可以了?
攔截器的實現(xiàn)原理就是動態(tài)代理,實現(xiàn)AOP機制。Spring 的代理實現(xiàn)有兩種:一是基于 JDK Dynamic Proxy 技術(shù)而實現(xiàn)的;二是基于 CGLIB 技術(shù)而實現(xiàn)的。如果目標(biāo)對象實現(xiàn)了接口,在默認(rèn)情況下Spring會采用JDK的動態(tài)代理實現(xiàn)AOP,CustomerServerImpl正是這種情況。
JDK動態(tài)代理生成的CustomerServiceImpl的代理類翻譯過來如下:
package com.example.demo;
import com.example.demo.inter.CustomerService;
public class CustomerServiceProxy implements CustomerService {
private CustomerService customerService;
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
public void doSomething1() {
doBefore();
customerService.doSomething1();
// 默認(rèn),所以不會執(zhí)行doBefore
customerService.doSomething2();
// 加入 AopContext.currentProxy的效果,完成切面效果
this.doSomething2();
}
public void doSomething2() {
doBefore();
customerService.doSomething2();
}
private void doBefore() {
System.out.println("do some important things before...");
}
}
這樣很直觀地明白為啥要使用AopContext.currentProxy了。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- SpringBoot中使用AOP打印接口日志的方法
- springboot?aop里的@Pointcut()的配置方式
- SpringBoot AOP方式實現(xiàn)多數(shù)據(jù)源切換的方法
- SpringBoot項目中使用AOP的方法
- 詳解基于SpringBoot使用AOP技術(shù)實現(xiàn)操作日志管理
- springboot配置aop切面日志打印過程解析
- SpringBoot使用AOP實現(xiàn)統(tǒng)計全局接口訪問次數(shù)詳解
- SpringBoot中使用AOP實現(xiàn)日志記錄功能
- SpringBoot使用AOP+注解實現(xiàn)簡單的權(quán)限驗證的方法
- SpringBoot中AOP的多種用途與實踐指南
相關(guān)文章
詳解MyBatis中Executor執(zhí)行SQL語句的過程
MyBatis中獲取SqlSession時會創(chuàng)建執(zhí)行器Executor并存放在SqlSession中,本篇文章將以MapperMethod的execute() 方法作為起點,對MyBatis中的一次實際執(zhí)行請求進(jìn)行說明,并結(jié)合源碼對執(zhí)行器Executor的原理進(jìn)行闡釋2023-07-07
解決gateway配合nacos路由報錯:Unable to find instance&
這篇文章主要介紹了解決gateway配合nacos路由報錯:Unable to find instance for XXX問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
SpringBoot 整合 Shiro 密碼登錄的實現(xiàn)代碼
這篇文章主要介紹了SpringBoot 整合 Shiro 密碼登錄的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
一篇文章了解Jackson注解@JsonFormat及失效解決辦法
這篇文章主要給大家介紹了關(guān)于如何通過一篇文章了解Jackson注解@JsonFormat及失效解決辦法的相關(guān)資料,@JsonFormat注解是一個時間格式化注解,用于格式化時間,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11

