Spring第六章:AOP(Aspect,自定義註解)

1.AOP方式

  1.1 Schema-based 方式(上篇有寫)  

  1.2.AspectJ

    1.2.1 每一個通知不須要實現接口或類

    1.2.2 配置 spring 配置文件是在<aop:config>的子標籤<aop:aspect>中配置

  AOP配置元素 | 描述 
  ------------ | -------------
  `<aop:advisor>` | 定義AOP通知器
  `<aop:after>`  | 定義AOP後置通知(無論該方法是否執行成功)
  `<aop:after-returning>` | 在方法成功執行後調用通知
  `<aop:after-throwing>` | 在方法拋出異常後調用通知
  `<aop:around>` | 定義AOP環繞通知
  `<aop:aspect>` | 定義切面
  `<aop:aspect-autoproxy>` | 定義`@AspectJ`註解驅動的切面
  `<aop:before>` | 定義AOP前置通知
  `<aop:config>` | 頂層的AOP配置元素,大多數的<aop:*>包含在<aop:config>元素內
  `<aop:declare-parent>` | 爲被通知的對象引入額外的接口,並透明的實現
  `<aop:pointcut>` | 定義切點

 

    1.2.3 使用AspectJ方式配置

      1.2.3.1 applicationContext.xml 
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置 Demo 類,測試使用 -->
    <bean id="demo" class="com.suncl.test.Demo"></bean>
    <bean id="myadvice" class="com.suncl.model.MyAdvice" ></bean>
    <aop:config>
        <aop:aspect ref="myadvice">
            <aop:pointcut expression="execution(* com.suncl.test.Demo.demo1(..)) " id="mypoint"/>
            <!--執行前置通知-->
            <aop:before method="beforeLog" pointcut-ref="mypoint" />
            <!-- <aop:after/> 後置通知,是否出現異常都執行 -->
            <aop:after method="afterLog" pointcut-ref="mypoint"/>
            <!--<aop:after-returing/> 後置通知,只有當切點正確執行時執行-->
            <aop:after-returning method="afterReturningLog"  pointcut-ref="mypoint"/>
            <!-- <aop:after-throwing 後置通知,只有當切點錯誤執行的時候執行-->
            <aop:after-throwing method="afterThrowingLog" pointcut-ref="mypoint"/>
            <!--環繞通知-->
            <aop:around method="aroundLog" pointcut-ref="mypoint"  />
        </aop:aspect>
    </aop:config>
</beans>
      1.2.3.2實體類
package com.suncl.test;

/**
 * Created by SCL-PC on 2019/2/28.
 */
public class Demo {

    public void demo(){
        System.out.println("執行了demo方法");
    }

    public void demo1(String a ,int b){
        System.out.println("執行了demo1111方法");
        //用來驗證出現錯誤的時候切點執行狀況
//        int i = 5/0;
    }


}
package com.suncl.model;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * Created by SCL-PC on 2019/3/3.
 */
public class MyAdvice {

    public void beforeLog() {
        System.out.println("開始執行前置通知  日誌記錄");
    }
    //    方法執行完後通知
    public void afterLog() {
        System.out.println("開始執行後置通知 日誌記錄");
    }
    //    執行成功後通知
    public void afterReturningLog() {
        System.out.println("方法成功執行後通知 日誌記錄");
    }
    //    拋出異常後通知
    public void afterThrowingLog() {
        System.out.println("方法拋出異常後執行通知 日誌記錄");
    }

    //    環繞通知
    public Object aroundLog(ProceedingJoinPoint joinpoint) {
        Object result = null;
        try {
            System.out.println("環繞通知開始 日誌記錄");
            long start = System.currentTimeMillis();

            //有返回參數 則需返回值
            result =  joinpoint.proceed();

            long end = System.currentTimeMillis();
            System.out.println("總共執行時長" + (end - start) + " 毫秒");
            System.out.println("環繞通知結束 日誌記錄");
        } catch (Throwable t) {
            System.out.println("出現錯誤");
        }
        return result;
    }

}

 

        1.2.3.3測試類
package com.suncl.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by SCL-PC on 2019/2/28.
 */
public class Test {


    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
         Demo demo = ac.getBean("demo",Demo.class);
        demo.demo1("a",1);
    }


}

 

      1.2.3.4運行結果
開始執行前置通知  日誌記錄
環繞通知開始 日誌記錄
執行了demo1111方法
總共執行時長16 毫秒
環繞通知結束 日誌記錄
方法成功執行後通知 日誌記錄
開始執行後置通知 日誌記錄

Process finished with exit code 0

 

 

   1.3 自定義註解(基於AspectJ)  

    1.3.1 每一個通知不須要實現接口或類

    1.3.2 使用自動以註解方式配置

      1.3.2.1 applicationContext.xml 
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--標識哪些類須要掃描註解-->
    <context:component-scan base-package="com.suncl"></context:component-scan>

    <!--使用配置註解,首先咱們要將切面在spring上下文中聲明成自動代理bean-->
    <aop:aspectj-autoproxy />

</beans>
      1.3.2.2實體類
package com.suncl.model;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * Created by SCL-PC on 2019/3/3.
 */
@Component
@Aspect
public class MyAdvice {

    // 配置切點 及要傳的參數
    @Pointcut(" execution(* com.suncl.test.Demo.demo1(..)) ")
    public void pointCut()
    {

    }

    @Before("pointCut()")
    public void beforeLog() {
        System.out.println("開始執行前置通知  日誌記錄");
    }

    //    方法執行完後通知
    @After("pointCut()")
    public void afterLog() {
        System.out.println("開始執行後置通知 日誌記錄");
    }

    //    執行成功後通知
    @AfterReturning("pointCut()")
    public void afterReturningLog() {
        System.out.println("方法成功執行後通知 日誌記錄");
    }

    //    拋出異常後通知
    @AfterThrowing("pointCut()")
    public void afterThrowingLog() {
        System.out.println("方法拋出異常後執行通知 日誌記錄");
    }

    //    環繞通知
    @Around("pointCut()")
    public Object aroundLog(ProceedingJoinPoint joinpoint) {
        Object result = null;
        try {
            System.out.println("環繞通知開始 日誌記錄");
            long start = System.currentTimeMillis();

            //有返回參數 則需返回值
            result =  joinpoint.proceed();

            long end = System.currentTimeMillis();
            System.out.println("總共執行時長" + (end - start) + " 毫秒");
            System.out.println("環繞通知結束 日誌記錄");
        } catch (Throwable t) {
            System.out.println("出現錯誤");
        }
        return result;
    }

}
 
package com.suncl.test;

import org.springframework.stereotype.Component;

/**
 * Created by SCL-PC on 2019/2/28.
 */
@Component
public class Demo {

    public void demo(){
        System.out.println("執行了demo方法");
    }

    public void demo1(String a ,int b){
        System.out.println("執行了demo1111方法");
        //用來驗證出現錯誤的時候切點執行狀況
//        int i = 5/0;
    }


}
       1.3.2.3測試類
package com.suncl.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by SCL-PC on 2019/2/28.
 */
public class Test {


    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
         Demo demo = ac.getBean("demo",Demo.class);
        demo.demo1("a",1);
    }


}
    1.3.2.4運行結果

 

環繞通知開始 日誌記錄
開始執行前置通知  日誌記錄
執行了demo1111方法
總共執行時長31 毫秒
環繞通知結束 日誌記錄
開始執行後置通知 日誌記錄
方法成功執行後通知 日誌記錄

Process finished with exit code 0

以上代碼地址:連接:https://pan.baidu.com/s/1xRWt4ndOAZfVJ_YER-aO1w  提取碼:jw84 spring

相關文章
相關標籤/搜索