天天看點

spring AOP 學習1、spring aop 基礎

1、spring aop 基礎

      spring 有兩大核心功能,DI 和 AOP。DI有助于應用之間的解耦,而AOP可以實作橫切關注點與他們所影響的對象之間的解耦。spring 隻支援方法級别的連接配接點。

     什麼是面向切面程式設計?切面能幫助我們子產品化橫切關注點。橫切關注點可以被子產品化為特殊的類,這些類被稱為切面。面向切面程式設計,可以讓我們把更多的注意力放在最重要的業務邏輯代碼,而次要關注的代碼放在切面裡。

2、通知

    通知定義了切面是什麼以及切面什麼使用。通知有五種類型:

  1.  Before: 在目标方法執行之前調用切面。
  2.  After:在目标方法之後調用切面。
  3. After-returning:目标方法執行之後調用通知
  4. AfterThrowing:在目标方法抛出異常後調用通知
  5. Around: 在目标方法調用之前和調用之後執行自定義的行為

3、程式設計實作

  (1)添加依賴

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.7.RELEASE</version>
</dependency>
           

(2)使用注解@EnableAspectJAutoProxy開啟 AOP功能支援

@EnableAspectJAutoProxy
@Configuration
public class BeanConfig {

    @Autowired
    private DruidDataSource druidDataSource;

    @Bean
    public JdbcTemplate jdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource);
        return jdbcTemplate;
    }

}
           

(3)具體代碼

  • 使用@Aspect注解表明這是一個切面Bean

  • 使用@Before @After等注解來表明通知類型

  • 使用@Pointcut來實作:重用切面表達式

  • 使用@Order來定義切面的優先級

package com.fengche.online.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 *  計算每一個controller執行的時間
 * Created by Administrator on  2018/9/20
 */
@Component
@Aspect
//設定切面的優先級:值越小,優先度越高
@Order(1)
public class TimeAopConfig {

    private static long beginTime = 0;


    /**
     *  重用切面表達式
     *             參考https://docs.spring.io/spring/docs/4.3.15.RELEASE/spring-framework-reference/html/aop.html
     *
     *             execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
     *             throws-pattern?)
     *
     *             execution(<修飾符模式>?<傳回類型模式><方法名模式>(<參數模式>)<異常模式>?)
     */
    @Pointcut(value = "execution(public * com.fengche.online.controller.*.*(..))")
    public void aspect(){

    }



    @Before(value = "aspect()")
    public void before(){
        beginTime = new Date().getTime();
    }

    @After(value = "aspect()")
    public void after(JoinPoint joinPoint){
        long currentTime = new Date().getTime();
        long runTime = (currentTime - beginTime);

        String packageName = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

//        logger.info();
        System.out.println(packageName + " " +methodName + " Action run time:  " + runTime + "ms");
    }


    /**
     * 異常通知
     * 在目标方法抛出異常後調用通知
     */
    @AfterThrowing("aspect()")
    public void afterThrowing(){

    }

    /**
     * 傳回通知
     * 在目标方法成功執行之後調用通知
     */
    @AfterReturning("aspect()")
    public void returning(){

    }

    /**
     * 環繞通知
     * 通知包裹了被通知的方法,在被通知的方
     * 法調用之前和調用之後執行自定義的行為
     */
    @Around("aspect()")
    public void aroud(){

    }
}
           

參考:

1、spring 實戰 第四版

2、官方文檔:

https://docs.spring.io/spring/docs/4.3.15.RELEASE/spring-framework-reference/html/aop.html

繼續閱讀