Spring AOP实例

来源:互联网 发布:淘宝美工和室内设计师 编辑:程序博客网 时间:2024/06/05 07:49

功能描述:在一个转账的业务中加入日志记录和校验(用Spring AOP)

创建账户表:

-- ------------------------------ Table structure for account-- ----------------------------DROP TABLE IF EXISTS `account`;CREATE TABLE `account` (  `account_id` char(16) NOT NULL,  `account_name` varchar(20) NOT NULL,  `currency` varchar(255) NOT NULL COMMENT '币种',  `balance` decimal(20,2) NOT NULL COMMENT '余额',  `open_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开户日期',  `open_place` varchar(20) NOT NULL DEFAULT '深圳' COMMENT '开户地点',  `account_state` enum('03','02','01','00') NOT NULL COMMENT '账户状态',  `password` varchar(255) NOT NULL COMMENT '账户密码',  PRIMARY KEY (`account_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ------------------------------ Records of account-- ----------------------------INSERT INTO `account` VALUES ('6226000098882323', '张三', 'CNY', '533.00', '2017-07-19 09:24:29', '深圳', '01', '123456');INSERT INTO `account` VALUES ('6226000098882929', '李四', 'CNY', '10116.00', '2017-07-19 09:25:52', '深圳', '01', '123456');

项目结构:
这里写图片描述

jar包:
这里写图片描述

1.创建账户实体类

package kay.com.entity;import java.math.BigDecimal;import java.util.Date;public class Account {    private String accountId;  //账户卡号    private String accountName; //账户姓名    private String currency;  //币种    private BigDecimal balance; //余额    private Date openTime; //开户时间    private String openPlace; //开户地点    private String accountState; //账户状态    private String password;   //账户密码    //getter  setter

2.查询账户和转账DAO(这里使用了原始的JDBC)

package kay.com.dao;import java.math.BigDecimal;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import kay.com.dao.AccountDAO;import kay.com.entity.Account;import kay.com.utils.DBUtils;public class AccountDAOImpl implements AccountDAO{    public Account queryAccountById(String accountId){              Connection connection=null;        PreparedStatement psmt=null;        ResultSet rs=null;        Account account=null;        String sql="select * from account where account_id = ?";            try {               connection=DBUtils.getConnection();            psmt=connection.prepareStatement(sql);            psmt.setString(1, accountId);            rs= psmt.executeQuery();                        while(rs.next()){                account=new Account();                account.setAccountId(rs.getString(1));                account.setAccountName(rs.getString(2));                account.setCurrency(rs.getString(3));                account.setBalance(rs.getBigDecimal(4));                account.setOpenTime(rs.getDate(5));                account.setOpenPlace(rs.getString(6));                account.setAccountState(rs.getString(7));                account.setPassword(rs.getString(8));            }            return account;        } catch (Exception e) {            e.printStackTrace();        }finally{            DBUtils.release(connection, psmt, rs);        }               return account;    }    /**     * 转账     */    public int transferCheckInOut(String mainAccountId, String outAccountId,            BigDecimal checkMoney){             Connection connection=null;        PreparedStatement psmt=null;        ResultSet rs=null;                  int count=0;  //更新行数                try {                       Account outAccount=queryAccountById(outAccountId);            BigDecimal oldOutBalance= outAccount.getBalance();            Account mainAccount=queryAccountById(mainAccountId);            BigDecimal oldMainBalance=mainAccount.getBalance();            connection=DBUtils.getConnection();            connection.setAutoCommit(false);            String sql="UPDATE account SET balance=? where account_id=?";            psmt=connection.prepareStatement(sql);            //更新主账户  减钱            oldMainBalance=oldMainBalance.subtract(checkMoney);            psmt.setBigDecimal(1,oldMainBalance);            psmt.setString(2, mainAccountId);            count= psmt.executeUpdate();                //更新被转入账户 金额 加钱            oldOutBalance=oldOutBalance.add(checkMoney);            psmt.setBigDecimal(1, oldOutBalance);            psmt.setString(2, outAccountId);            count+=psmt.executeUpdate();            connection.commit();            //提交事物        } catch (Exception e) {            try {                connection.rollback();   //事务回滚            } catch (SQLException e1) {                e1.printStackTrace();            }            e.printStackTrace();        }finally{            DBUtils.release(connection, psmt, rs);        }        return count;    }}

3.转账Service

package kay.com.service;import java.math.BigDecimal;import org.springframework.beans.factory.annotation.Autowired;import kay.com.dao.AccountDAO;public class AccountServiceImpl implements AccountService{    private AccountDAO accountDAO;    public AccountDAO getAccountDAO() {        return accountDAO;    }    public void setAccountDAO(AccountDAO accountDAO) {        this.accountDAO = accountDAO;    }    public int transferCheckInOut(String mainAccountId, String outAccountId,            BigDecimal checkMoney) {        return accountDAO.transferCheckInOut(mainAccountId, outAccountId, checkMoney);    }}

5.日志切面类和验证切面类

模拟日志

package kay.com.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;public class LogAspect {    public void doAfter(JoinPoint jp) {          System.out.println("日志记录---- doafter方法 : " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());      }      public Object doAround(ProceedingJoinPoint pjp) throws Throwable {          long time = System.currentTimeMillis();          Object retVal = pjp.proceed();          time = System.currentTimeMillis() - time;          System.out.println("日志记录---- 执行时间: " + time + " ms");          return retVal;      }      public void doBefore(JoinPoint jp) {          System.out.println("日志记录---- before方法: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());          Object[] args=jp.getArgs();  //获取参数        System.out.println("日志记录---- 转出账户:"+args[0] +" 转入账户: "+args[1] +" 转出金额:"+ args[2]);    }      public void doThrowing(JoinPoint jp, Throwable ex) {          System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");          System.out.println(ex.getMessage());      }  }

模拟验证

package kay.com.aop;import java.math.BigDecimal;import kay.com.dao.AccountDAO;import kay.com.entity.Account;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;public class ValidateAspect {    private AccountDAO accountDAO;   //注入dao    public AccountDAO getAccountDAO() {        return accountDAO;    }    public void setAccountDAO(AccountDAO accountDAO) {        this.accountDAO = accountDAO;    }    public Object doAround(ProceedingJoinPoint pj) throws Throwable {         System.out.println("校验检测----:");        Object[] args=pj.getArgs();        Account mainAccount=accountDAO.queryAccountById((String)args[0]);        Account outAccount=accountDAO.queryAccountById((String)args[1]);        if(mainAccount==null){            System.out.println("账户:"+args[0]+"不存在!转账未执行");            return 0;        }else if(outAccount==null){            System.out.println("转入账户:"+args[1]+"不存在!转账未执行");            return 0;        }          BigDecimal checkMoney=(BigDecimal)args[2];        BigDecimal mainBalance=mainAccount.getBalance();        if(checkMoney.compareTo(mainBalance)>0){            System.out.println("余额不足,无法转出");            return 0;        }else {            System.out.println("无异常");        }        Object retVal = pj.proceed();          return retVal;      }      public void doThrowing(JoinPoint jp, Throwable ex) {          System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");          System.out.println(ex.getMessage());      }  }

6.spring配置

<?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">    <aop:config>      <!-- 日志切面 -->        <aop:aspect id="logAsp" ref="logAspect">                          <aop:pointcut id="businessService" expression="execution(* kay.com.service.*.transferCheckInOut(..))" />              <aop:before pointcut-ref="businessService" method="doBefore"/>              <aop:after pointcut-ref="businessService" method="doAfter"/>              <aop:around pointcut-ref="businessService" method="doAround"/>              <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>          </aop:aspect>      <!-- 验证切面 -->            <aop:aspect id="validateAsp" ref="validateAspect">            <aop:pointcut expression="execution(* kay.com.service.*.*(..))" id="validateService"/>            <aop:around pointcut-ref="validateService" method="doAround"/>          </aop:aspect>    </aop:config>     <bean id="logAspect" class="kay.com.aop.LogAspect"></bean>   <!--  注入一个dao对象 -->   <bean id="validateAspect" class="kay.com.aop.ValidateAspect">        <property name="accountDAO" ref="accountDAO"></property>   </bean>   <!-- service的实例 -->   <bean id="myservice" class="kay.com.service.AccountServiceImpl">        <property name="accountDAO" ref="accountDAO"></property>   </bean>   <bean id="accountDAO" class="kay.com.dao.AccountDAOImpl"></bean></beans>

7.MainTest

package kay.com;import java.math.BigDecimal;import kay.com.service.AccountService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest {    public static void main(String[] args) {        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");        AccountService accountService=(AccountService) context.getBean("myservice");        //余额不足时        //accountService.transferCheckInOut("6226000098882323", "6226000098882929", new BigDecimal("1000.00"));        //账户不存在时        accountService.transferCheckInOut("6226000098882321", "6226000098882929", new BigDecimal("200.00"));    }}

测试结果

这里写图片描述

原创粉丝点击