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有更深入的認識,其實他相對于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)的。如果目標對象實現(xià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();
// 默認,所以不會執(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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis開發(fā)Dao層的兩種方式實現(xiàn)(原始Dao層開發(fā))
這篇文章主要介紹了MyBatis開發(fā)Dao層的兩種方式實現(xiàn)(原始Dao層開發(fā)),并對數(shù)據(jù)庫進行增刪查改,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12
Java使用自定義注解+反射實現(xiàn)字典轉(zhuǎn)換代碼實例
這篇文章主要介紹了Java使用自定義注解+反射實現(xiàn)字典轉(zhuǎn)換代碼實例,注解是一種能被添加到j(luò)ava代碼中的元數(shù)據(jù),類、方法、變量、參數(shù)和包都可以用注解來修飾,注解對于它所修飾的代碼并沒有直接的影響,需要的朋友可以參考下2023-09-09

