Spring框架學習3——AOP的使用

前言:這個文章的定位不是實現的步驟,而是實現過程中遇到的問題。並且我寫的步驟是別人的步驟的記錄,算不了什麼,後面對使用過程中遇到的問題以及解決的方法纔是自己寫的,有價值的地方。

寫這篇文章的出發點一個是爲了保障自己學以致用,一個是查漏補缺。

而且很多教程雖然說按照那個步驟可以成功,但也可能不成功,要麼是自己操作有誤,要麼是版本變了,還有可能自己基礎沒學好,前置知識不夠。我最開始寫Java的時候連創建父類和接口類都不會,直接創建一個類,然後複製粘貼,最後報錯。僵硬~

寫這類博客,即寫步驟,又寫操作過程中遇到的問題,然後從中吸取教訓,可以讓成功的概率更大。

同時sprig框架學習我打算按照五部分(IOC、bean、AOP、數據庫、事務)進行梳理,最後加個綜合大應用。學前在注意的情況下,會寫前置知識。

Java基礎:https://blog.csdn.net/weixin_42875245/article/details/105951858

IDE使用:https://blog.csdn.net/weixin_42875245/article/details/105867499

Spring學習筆記:https://blog.csdn.net/weixin_42875245/article/details/105631818

Spring見解:https://blog.csdn.net/Haidaiya/article/details/105611801

 

一、引入包

1在eclipse基礎開發環境創建一個springtest03的動態web項目,將spring的4個基本包以及commons-logging的包,還有spring-aop-4.3.6.RELEASE.jar、spring-aspects-4.3.6.RELEASE.jar、aspectjweaver-1.8.10.jar複製到lib目錄中,併發布到類路徑下。

 

二、基於XML的聲明式AspectJ

1在src創建一個com.ssm.aspectj包,在包中創建接口UserDAO,並在接口中編寫添加和刪除的方法。代碼如下:

2在com.ssm.aspectj包中創建接口實現類UserDaoImpl,並實現接口中的方法。代碼如下:

3在src目錄下創建在com.ssm.aspectj.xml包,在包中創建切面類MyAspect,並在類中分別定義不同類型的 通知。代碼如下

4在com.ssm.aspectj.xml包中創建配置文件applicationContext.xml,並編寫相關配置,代碼如下。

5在com.ssm.aspectj.xml包中創建測試類TestXmlAspectJ,代碼如下

6測試:

 

三、基於註解的聲明式aspectj

1在src目錄下創建在com.ssm.aspectj.annotation包,在包中創建切面類MyAspect。代碼如下。(在UserDaoImpl中添加註解@Repository(“UserDao”))

2在com.ssm.aspectj.annotation包中創建配置文件applicationContext.xml,並編寫相關配置,代碼如下。

3在com.ssm.aspectj.annotation包中創建測試類TestAnotation,代碼如下

4測試:

與XML相比,使用註解的方式更加方便和簡單,且可以不用寫實現AOP功能所配置的代碼,提高開發效率。

 

四、第一個實驗

1創建接口類UserDao

package com.ssm.aspectj;

public interface UserDao {

    public void addUser();

    public void deleteUser();

}

2創建接口實現類UserDaoImpl

package com.ssm.aspectj;

import org.springframework.stereotype.Repository;

@Repository("userDao")//用於註解方式

public class UserDaoImpl implements UserDao {

    public void addUser() {

        System.out.println("添加用戶");

        // 用於設置異常

        // int i=10/0;

    }

    public void deleteUser() {

        System.out.println("刪除用戶");

    }

}

3創建MyAspect類

package com.ssm.aspectj.xml;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

/**

 * 切面類,在此類中編寫通知

 */

public class MyAspect {

    //前置通知

    public void myBefore(JoinPoint joinPoint){

        System.out.print("前置通知:模擬執行權限檢查..");

        System.out.print("目標類是:"+joinPoint.getTarget());

        System.out.println(",被植入增強處理的目標方法爲:"+joinPoint.getSignature().getName());

    }

    //後置通知

    public void myAfterReturning(JoinPoint joinPoint) {

        System.out.print("後置通知:模擬記錄日誌..");

        System.out.println("被植入增強處理的目標方法爲:" + joinPoint.getSignature().getName());

    }

    /**

     * 環繞通知

     * ProceedingJoinPointJoinPoint的子接口,表示可執行目標方法

     * 1.必須是Object類型的返回值

     * 2.必須接收一個參數,類型爲ProceedingJoinPoint

     * 3.必須throws Throwable

     */

    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{

        //開始

        System.out.println("環繞開始:執行目標方法之前,模擬開啓事務..");

        //執行當前目標方法

        Object obj=proceedingJoinPoint.proceed();

        //結束

        System.out.println("環繞結束:執行目標方法之後,模擬關閉事務..");

        return obj;

    }

    //異常通知

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){

        System.out.println("異常通知:出錯了"+e.getMessage());

    }

    //最終通知

    public void myAfter(){

        System.out.println("最終通知:模擬方法結束後釋放資源..");

    }

}

4創建配置文件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-4.3.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!-- 1 目標類 -->

    <bean id="userDao" class="com.ssm.aspectj.UserDaoImpl" />

    <!-- 2 切面 -->

    <bean id="myAspect" class="com.ssm.aspectj.xml.MyAspect" />

    <!-- 3 aop編程 -->

    <aop:config>

        <!-- 1.配置切面 -->

        <aop:aspect id="aspect" ref="myAspect">

            <!-- 2.配置切入點 -->

            <aop:pointcut expression="execution(* com.ssm.aspectj.*.*(..))"    id="myPointCut" />

            <!-- 3.配置通知 -->

                <!-- 前置通知 -->

                <aop:before method="myBefore" pointcut-ref="myPointCut" />

                <!--後置通知-->

                <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>

                <!--環繞通知 -->

                <aop:around method="myAround" pointcut-ref="myPointCut" />

                <!--異常通知 -->

                <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" />

                <!--最終通知 -->

                <aop:after method="myAfter" pointcut-ref="myPointCut" />

        </aop:aspect>

    </aop:config>

</beans>

5創建測試類TestXmlAprectJ

package com.ssm.aspectj.xml;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.aspectj.UserDao;

public class TestXmlAspectJ {

    public static void main(String[] args) {

        String xmlPath="com/ssm/aspectj/xml/applicationContext.xml";

        ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);

        //從容器中獲得內容

        UserDao userDao=(UserDao)applicationContext.getBean("userDao");

        //執行方法

        userDao.addUser();

    }

}

 

五、第二個實驗

1創建切面類

package com.ssm.aspectj.annotation;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

/**

 * 切面類,在此類中編寫通知

 */

@Aspect

@Component

public class MyAspect {

    //定義切入點表達式

    @Pointcut("execution(* com.ssm.aspectj.*.*(..))")

    //使用一個返回值爲void、方法體爲空的方法來命名切入點

    public void myPointCut(){}

    //前置通知

    @Before("myPointCut()")

    public void myBefore(JoinPoint joinPoint){

        System.out.print("前置通知:模擬執行權限檢查..");

        System.out.print("目標類是:"+joinPoint.getTarget());

        System.out.println(",被植入增強處理的目標方法爲:"+joinPoint.getSignature().getName());

    }

    //後置通知

    @AfterReturning(value="myPointCut()")

    public void myAfterReturning(JoinPoint joinPoint) {

        System.out.print("後置通知:模擬記錄日誌..");

        System.out.println("被植入增強處理的目標方法爲:" + joinPoint.getSignature().getName());

    }

    /**

     * 環繞通知

     * ProceedingJoinPointJoinPoint的子接口,表示可執行目標方法

     * 1.必須是Object類型的返回值

     * 2.必須接收一個參數,類型爲ProceedingJoinPoint

     * 3.必須throws Throwable

     */

    @Around("myPointCut()")

    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{

        //開始

        System.out.println("環繞開始:執行目標方法之前,模擬開啓事務..");

        //執行當前目標方法

        Object obj=proceedingJoinPoint.proceed();

        //結束

        System.out.println("環繞結束:執行目標方法之後,模擬關閉事務..");

        return obj;

    }

    //異常通知

    @AfterThrowing(value="myPointCut()",throwing="e")

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){

        System.out.println("異常通知:出錯了"+e.getMessage());

    }

    //最終通知

    @After("myPointCut()")

    public void myAfter(){

        System.out.println("最終通知:模擬方法結束後釋放資源..");

    }

}

2創建配置文件

<?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-4.3.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <!-- 指定需要掃描的包,使註解生效 -->

    <context:component-scan base-package="com.ssm" />

    <!-- 啓動基於註解的聲明式AspectJ支持 -->

    <aop:aspectj-autoproxy />

</beans>

3創建測試類

package com.ssm.aspectj.annotation;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.aspectj.UserDao;

public class TestAnnotation {

    public static void main(String[] args) {

        String xmlPath="com/ssm/aspectj/annotation/applicationContext.xml";

        ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);

        //從容器中獲得內容

        UserDao userDao=(UserDao)applicationContext.getBean("userDao");

        //執行方法

        userDao.addUser();

    }

}

 

結論:有些僵硬,沒遇到問題,還想着與報錯鬥智鬥勇。回頭從eclipse轉IDEA試試。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章