(九)Spring-AOP 注解配置详解

一、配置过程

  •  配置依赖项,注意的是切入点表达式解析的依赖包。
  •  配置切面类:
       @Aspect注解,表示当前类是一个切面类
       @Pointcut替代xml文件中的切入点表达式,并且写入切入点表达式
      @Before @AfterThrowing @AfterReturning @After @Around分别替代xml文件中的前置、异常、后置、最终以及环绕通知,需要注意的是,环绕通知与前面几个通知选择其一即可,环绕通知需要写一个方法为public Object aopAround(ProceedingJoinPoint joinPoint),参数必须为要求的参数,然后通过joinPoint来替代动态代理中的invoke
      其余注解的配置与之前的配置一致,需要的注意的是在MyConfiguration类前需要加注解@EnableAspectJAutoProxy来开启AOP代理。

二、配置步骤

 2.1 依赖项



    4.0.0
    
        1.8
        1.8
    
    org.example
    spring-account-annoation
    1.0-SNAPSHOT
    jar
    
        
            org.springframework
            spring-context
            5.0.2.RELEASE
        
        
            org.springframework
            spring-aop
            5.0.2.RELEASE
        
        
            org.springframework
            spring-test
            5.0.2.RELEASE
            test
        
        
            org.springframework
            spring-context
            5.0.2.RELEASE
        
        
            junit
            junit
            4.12
            test
        
        
            mysql
            mysql-connector-java
            5.1.48
        
        
            org.aspectj
            aspectjweaver
            1.8.7
        
        
            commons-dbutils
            commons-dbutils
            1.7
        
        
            c3p0
            c3p0
            0.9.1.2
        
    

 2.2 配置切面类及通知方法

package com.util;

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.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.SQLException;

/**
 * Created with IntelliJ IDEA.
 *
 * @author : gxm
 * @date : 2020/5/5
 * @time : 21:25
 * @projectName : spring-account
 * @description : 工具类,控制连接的事务,注解中配置为切面类
 *  四个通知的注解使用会有顺序调用问题,开发时应选择环绕通知,手动控制通知
 * To change this template use File | Settings | File Templates.
 * Description:
 **/
@Component("transactionManager")
@Aspect
public class TransactionManager {
    @Resource(name = "connectionUtils")
    private ConnectionUtils connectionUtils;

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    /**
     * @author gxm
     * @date 2020/5/8 15:38
     * @description 配置切入点表达式
     * @param
     * @return void
     * @since version-1.0
     */
    @Pointcut("execution(* *.*.*.AccountServiceImpl.*(..))")
    private void pointCut(){}
    /**
     * @param
     * @return void
     * @author gxm
     * @date 2020/5/5 21:30
     * @description 关闭当前当前线程连接的自动提交
     * @since version-1.0
     */
    @Before("pointCut()")
    public void beginTransaction() {
        System.out.println("beginTransaction");
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    /**
     * @param
     * @return void
     * @author gxm
     * @date 2020/5/5 21:30
     * @description 出错就回滚
     * @since version-1.0
     */
    @AfterThrowing("pointCut()")
    public void rollBack() {

        try {
            connectionUtils.getThreadConnection().rollback();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
        System.out.println("rollBack");
    }

    /**
     * @param
     * @return void
     * @author gxm
     * @date 2020/5/5 21:32
     * @description 提交操作
     * @since version-1.0
     */
    @AfterReturning("pointCut()")
    public void commit() {
        System.out.println("commit");
        try {
            connectionUtils.getThreadConnection().commit();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    /**
     * @param
     * @return void
     * @author gxm
     * @date 2020/5/5 21:33
     * @description This is description of method
     * @since version-1.0
     */
    @After("pointCut()")
    public void release() {
        System.out.println("release");
        try {
            connectionUtils.getThreadConnection().close();
            connectionUtils.remove();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }
    /**
     * @author gxm
     * @date 22:44
     * @description 环绕通知,类似于动态代理,手动实现aop过程
     * @param joinPoint 1
     * @return java.lang.Object
     * @since version-1.0
     */
    //@Around("pointCut()")
    public Object aopAround(ProceedingJoinPoint joinPoint) {
        Object proceed = null;
        try {
            // 1. 前置通知
            beginTransaction();
            // 2. 环绕通知
            proceed = joinPoint.proceed(joinPoint.getArgs());
            // 3. 后置通知
            commit();
        } catch (Throwable throwable) {
            // 4. 异常通知
            rollBack();
            throw new RuntimeException(throwable);
        }finally {
            // 5. 最终通知
            release();
        }
        return proceed;
    }
}

 2.3 开启AOP代理

@Configuration
@ComponentScan(value = "com")
@PropertySource("classpath:db.properties")
@Import(JdbcConfig.class)
@EnableAspectJAutoProxy
public class MyConfiguration {
}

 2.4 测试AOP代理是否正常执行

package com.service.impl;

import com.config.MyConfiguration;
import com.domain.Account;
import com.service.IAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.util.List;

import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyConfiguration.class)
public class AccountServiceImplTest {
    @Autowired
    private IAccountService accountService;

    @Qualifier("account")
    @Autowired
    private Account account1;

    @Qualifier("account")
    @Autowired
    private Account account2;
        //  更新数据库时,添加如下测试代码,报错后,并未提交到数据库,说明测试成功
        //accounts1.forEach(this::updateAccount);
       // int a = 1/0;
       // accounts2.forEach(this::updateAccount);
    @Test
    public void transfer() {
        account1.setId(17);
        account2.setId(18);
        accountService.transfer(account2, account1, 10f);
    }
  
    @Test
    public void saveAccount() {
        accountService.saveAccount(account1);
        accountService.saveAccount(account2);
    }

    @Test
    public void queryAll() {
        List accounts = accountService.queryAll();
        accounts.forEach((System.out::println));
    }

    @Test
    public void queryById() {
        List accounts = accountService.queryById(account1.getId());
        accounts.forEach(System.out::println);
    }

    @Test
    public void queryByName() {
        List accounts = accountService.queryByName(account1.getName());
        accounts.forEach(System.out::println);
    }


    @Test
    public void updateAccount() {
        account1.setBalance(account1.getBalance()+1);
        accountService.updateAccount(account1);
    }

    @Test
    public void deleteAccountById() {
        accountService.deleteAccountById(account1.getId());
    }

    @Test
    public void setAccountDao() {
    }
}

 2.5 github完整代码

https://github.com/GaoXiaoMing-BUPT/spring-account-annoation

你可能感兴趣的:((九)Spring-AOP 注解配置详解)