1. 程式人生 > >Spring --13.Spring中AOP程式設計(註解方式)

Spring --13.Spring中AOP程式設計(註解方式)

1、基於註解AOP入門案例

1.2、建立工程引入依賴

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
    </dependencies>

1.3、編寫Spring配置檔案

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">

    <!--開啟Spring註解掃描-->
    <context:component-scan base-package="com.day03"> </context:component-scan>
    <!--開啟aspectj自動代理-->
    <aop:aspectj-autoproxy> </aop:aspectj-autoproxy>

</beans>

log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout, file

1.4、建立介面和實現類

UserDao.java

package com.day03.dao;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
public interface UserDao {
    public abstract void save();
    public abstract Integer delete();
    public abstract Integer update(int a, int b);
    public abstract void list();
}

UserDaoImpl.java

package com.day03.dao.Impl;

import com.day03.dao.UserDao;
import org.springframework.stereotype.Repository;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save方法。。。。。。。。。。。");
    }

    @Override
    public Integer delete() {
        System.out.println("delete方法。。。。。。。。。。。");
        return 100;
    }

    @Override
    public Integer update(int a, int b) {
        System.out.println("update......................");
        int c = a + b;
        return c;
    }

    @Override
    public void list() {
        //int a = 10/0;
        System.out.println("List...........................");
    }
}

1.5、編寫切面類

MyAspectAnno.java

package com.day03.aspect;

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

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 9:30 2018/11/13
 */
@Component
@Aspect //表示該類是一個切面類
public class MyAspectAnno {
}

1.6、編寫測試類

MyTestAnno.java

package com.day03.test;

import com.day03.dao.UserDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 9:32 2018/11/13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class MyTestAnno {

    @Autowired
    private UserDao userDao;

    //前置通知
    @Test
    public void tes1(){
        userDao.save();
    }

    //後置通知
    @Test
    public void test2(){
        userDao.delete();
    }

    //環繞通知
    @Test
    public void test3(){
        userDao.update(5,10);
    }
    //異常通知
    @Test
    public void test4(){
        userDao.list();
    }
}

2、用註解來配置各種通知

前置通知、後置通知、環繞通知、異常通知、最終通知

MyAspectAnno.java切面類

package com.day03.aspect;

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

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 9:30 2018/11/13
 */
@Component
@Aspect //表示該類是一個切面類
public class MyAspectAnno {

    /**
     * 前置通知方法 應用場景: 許可權控制 (許可權不足,丟擲異常)、 記錄方法呼叫資訊日誌 joinPoint:連線點,指的是被增強的那個方法
     * @param jp
     */
    @Before("execution(* com.day03.dao.Impl.UserDaoImpl.save(..))")
    public void before(JoinPoint jp){
        String username = "admin";
        if (!"user".equals(username)){
            throw new RuntimeException("你沒有對類"+jp.getTarget().getClass().getName()+"中的方法"+jp.getSignature().getName()+"訪問許可權!");
        }
    }

    /**
     * 後置通知方法 應用場景: ATM取款機取款後,自動下發簡訊 引數result:被增強那個方法的返回值
     *     returning屬性指定目標方法返回值的名字
     */
    @AfterReturning(value = "execution(* com.day03.dao.Impl.UserDaoImpl.delete(..))",returning = "result")
    public void afterRunnings(JoinPoint jp,Object result){

        System.out.println("你在ATM機上取了:"+result+"元");
    }


     /**
     * 環繞通知方法 應用場景:事務處理
     * proceedingJoinPoint
     *  正在執行的連線點
     * @return
     */
    @Around("execution(* com.day03.dao.Impl.UserDaoImpl.update(..))")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("開啟事務");
        Object[] args = pjp.getArgs();//獲取引數
        Object proceed = null;
        try {
            proceed = pjp.proceed(args);
//            int a = 10/0;
            System.out.println("proceed = " + proceed);
            System.out.println("提交事務");
        } catch (Throwable throwable) {
            System.out.println("回滾事務");
        }

        return proceed;
    }


    /**
     * 異常通知方法、應用:異常處理
     * @param ex
     * 目標方法丟擲的異常
     */
    @AfterThrowing(value = "execution(* com.day03.dao.Impl.UserDaoImpl.list(..))",throwing = "ex")
    public void afterThroing(JoinPoint jp , Throwable ex){
        throw  new RuntimeException("在這個類:"+jp.getTarget().getClass().getName()+"中的方法"+jp.getSignature().getName()+"丟擲異常"+ex.getMessage());
    }

    /**
     *最終通知方法 應用場景:釋放資源 (關閉檔案、 關閉資料庫連線、 網路連線、 釋放記憶體物件 )
     *@param joinPoint  被增強的那個方法
     */
    @After("execution(* com.day03.dao.Impl.UserDaoImpl.list(..))")
    public void after(JoinPoint joinPoint){
        System.out.println("釋放資源、對應的類為"+joinPoint.getTarget().getClass().getName()+"方法為:"+joinPoint.getSignature().getName());
    }

}

UserDaoImpl.java

package com.day03.dao.Impl;

import com.day03.dao.UserDao;
import org.springframework.stereotype.Repository;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save方法。。。。。。。。。。。");
    }

    @Override
    public Integer delete() {
        System.out.println("delete方法。。。。。。。。。。。");
        return 100;
    }

    @Override
    public Integer update(int a, int b) {
        System.out.println("update......................");
        int c = a + b;
        return c;
    }

    @Override
    public void list() {
        //int a = 10/0;
        System.out.println("List...........................");
    }
}

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">

    <!--開啟Spring註解掃描-->
    <context:component-scan base-package="com.day03"> </context:component-scan>
    <!--開啟aspectj自動代理-->
    <aop:aspectj-autoproxy> </aop:aspectj-autoproxy>

</beans>

MyTestAnno.java

package com.day03.test;

import com.day03.dao.UserDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 9:32 2018/11/13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class MyTestAnno {

    @Autowired
    private UserDao userDao;

    //前置通知
    @Test
    public void tes1(){
        userDao.save();
    }

    //後置通知
    @Test
    public void test2(){
        userDao.delete();
    }

    //環繞通知
    @Test
    public void test3(){
        userDao.update(5,10);
    }
    //異常通知
    @Test
    public void test4(){
        userDao.list();
    }
}