Springboot--實(shí)戰(zhàn)開(kāi)發(fā)--AOP(三十八)

一、AOP簡(jiǎn)介

??面向切面的程序設(shè)計(jì)(Aspect-oriented programming,AOP,又譯作面向方面的程序設(shè)計(jì)、剖面導(dǎo)向程序設(shè)計(jì))是計(jì)算機(jī)科學(xué)中的一種程序設(shè)計(jì)思想,旨在將橫切關(guān)注點(diǎn)與業(yè)務(wù)主體進(jìn)行進(jìn)一步分離,以提高程序代碼的模塊化程度。通過(guò)在現(xiàn)有代碼基礎(chǔ)上增加額外的通知(Advice)機(jī)制,能夠?qū)Ρ宦暶鳛椤扒悬c(diǎn)(Pointcut)”的代碼塊進(jìn)行統(tǒng)一管理與裝飾,如“對(duì)所有方法名以‘set*’開(kāi)頭的方法添加后臺(tái)日志”。該思想使得開(kāi)發(fā)人員能夠?qū)⑴c代碼核心業(yè)務(wù)邏輯關(guān)系不那么密切的功能(如日志功能)添加至程序中,同時(shí)又不降低業(yè)務(wù)代碼的可讀性。面向切面的程序設(shè)計(jì)思想也是面向切面軟件開(kāi)發(fā)的基礎(chǔ)。

??面向切面的程序設(shè)計(jì)將代碼邏輯切分為不同的模塊(即關(guān)注點(diǎn)(Concern),一段特定的邏輯功能)。幾乎所有的編程思想都涉及代碼功能的分類,將各個(gè)關(guān)注點(diǎn)封裝成獨(dú)立的抽象模塊(如函數(shù)、過(guò)程、模塊、類以及方法等),后者又可供進(jìn)一步實(shí)現(xiàn)、封裝和重寫。部分關(guān)注點(diǎn)“橫切”程序代碼中的數(shù)個(gè)模塊,即在多個(gè)模塊中都有出現(xiàn),它們即被稱作“橫切關(guān)注點(diǎn)(Cross-cutting concerns, Horizontal concerns)”。
??Aspect(切面): Aspect 聲明類似于 Java 中的類聲明,在 Aspect 中會(huì)包含著一些 Pointcut 以及相應(yīng)的 Advice。
??Joint point(連接點(diǎn)):表示在程序中明確定義的點(diǎn),典型的包括方法調(diào)用,對(duì)類成員的訪問(wèn)以及異常處理程序塊的執(zhí)行等等,它自身還可以嵌套其它 joint point。
??Pointcut(切點(diǎn)):表示一組 joint point,這些 joint point 或是通過(guò)邏輯關(guān)系組合起來(lái),或是通過(guò)通配、正則表達(dá)式等方式集中起來(lái),它定義了相應(yīng)的 Advice 將要發(fā)生的地方。
??Advice(增強(qiáng)):Advice 定義了在 Pointcut 里面定義的程序點(diǎn)具體要做的操作,它通過(guò) before、after 和 around 來(lái)區(qū)別是在每個(gè) joint point 之前、之后還是代替執(zhí)行的代碼。
??Target(目標(biāo)對(duì)象):織入 Advice 的目標(biāo)對(duì)象.。
??Weaving(織入):將 Aspect 和其他對(duì)象連接起來(lái), 并創(chuàng)建 Adviced object 的過(guò)程

二、Maven依賴

<!--aop-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

三、日志處理

  1. 配置
spring.aop.proxy-target-class=true

該屬性值默認(rèn)為false,表示使用JDK動(dòng)態(tài)代理織入增強(qiáng);當(dāng)值為true時(shí),表示使用CGLib動(dòng)態(tài)代理織入增強(qiáng);但是,即使設(shè)置為false,如果目標(biāo)類沒(méi)有生命接口,則Spring將自動(dòng)使用CGLib動(dòng)態(tài)代理.

因?yàn)樵贏OP的默認(rèn)配置屬性中,spring.aop.auto屬性默認(rèn)是開(kāi)啟的,也就是說(shuō)只要引入了AOP依賴后,默認(rèn)已經(jīng)增加了@EnableAspectJAutoProxy。
一個(gè)類變成切面類,需要兩步,
① 在類上使用 @Component 注解 把切面類加入到IOC容器中
② 在類上使用 @Aspect 注解 使之成為切面類

  1. 切面類
@Aspect
@Component
@Slf4j
public class WebLogAcpect {
    /**
     * 定義切入點(diǎn),切入點(diǎn)為com.example.aop下的所有函數(shù)
     */
    @Pointcut("execution(public * com.xtsz.aop..*.*(..))")
    public void webLog(){}

    /**
     * 前置通知:在連接點(diǎn)之前執(zhí)行的通知
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到請(qǐng)求,記錄請(qǐng)求內(nèi)容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 記錄下請(qǐng)求內(nèi)容
        log.info("URL : " + request.getRequestURL().toString());
        log.info("HTTP_METHOD : " + request.getMethod());
        log.info("IP : " + request.getRemoteAddr());
        log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret",pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請(qǐng)求,返回內(nèi)容
        log.info("RESPONSE : " + ret);
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容