springboot aop切面-动态数据源

事务与动态数据源不能同时有效。用了动态数据源,事务就不会生效。

lxt:
  pointcut:
    #在controller之前切入,初步数据验证 order为切入时机,越小越先切入
    controller:
      value: execution(public * cn.lexiaotongvip.www.control..*.*(..))
      order: 1
    service:
      value: execution(* cn.lexiaotongvip.www.service..*.*(..))
      order: 3
      is-dynamic-db: true
package cn.lexiaotongvip.www.config;

import cn.lexiaotongvip.www.config.dbConfig.DataSourceEnum;
import cn.lexiaotongvip.www.config.dbConfig.DataSourceHolder;
import cn.lexiaotongvip.www.config.dbConfig.MyDataSource;
import cn.lexiaotongvip.www.control.enums.ResCodeEnum;
import cn.lexiaotongvip.www.control.pojo.qo.ReqParQO;
import cn.lexiaotongvip.www.control.pojo.vo.ResultVO;
import cn.lexiaotongvip.www.service.IDataService;
import org.aopalliance.intercept.MethodInterceptor;
import org.slf4j.Logger;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import java.lang.reflect.Method;

/**
 * 乐校通切面
 * 1、controller前的操作:日志、校验、解析
 * 2、service 事务全局配置
 * 3、配置事务的地方加入动态数据源切换
 *
 * @author chenzy
 * @since 2019.12.17
 */

@Configuration
//@ConditionalOnProperty(prefix = "lxt",name = "pointcut")
public class LXTAspect {
    @Autowired
    private Logger clientLog;

    @Autowired
    private IDataService dataService;

    /**
     * //执行业务前操作:日志、校验、解析
     * @return
     */
    @Bean
//    @ConditionalOnProperty(prefix = "lxt.pointcut.controller",name = "value")
    public AspectJExpressionPointcutAdvisor dataAspect(@Value("${lxt.pointcut.controller.value}") String pointcut
    ,@Value("${lxt.pointcut.controller.order}") Integer order) {
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(pointcut);
        advisor.setOrder(order);
        advisor.setAdvice((MethodInterceptor) invocation -> {
            Object verifyResult = dataVerify(invocation.getMethod().getName(), invocation.getArguments());
            if (verifyResult != null) {
                return verifyResult;
            }
            //执行业务方法
            try {
                Object result = invocation.proceed();
                return result;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                return new ResultVO(ResCodeEnum.UnknownExce);
            }
        });
        return advisor;
    }
    /**
     * 调用业务service前后切入
     * 1、日志
     * 2、数据校验
     * 3、数据解析
     */
    private Object dataVerify(String methodName, Object[] args) {
        /*
         * 第一个参数是ReqParQO类型才记录日志、数据校验、解析数据
         */
        if (args != null && args.length >= 1 && args[0] instanceof ReqParQO) {
            ReqParQO reqParQO = (ReqParQO) args[0];
            //1、日志:记录请求参数
            clientLog.info("[{}的请求参数]:{}", reqParQO.getRequestType().getMsg(), reqParQO.toString());
            //2、数据校验
            ResultVO result = dataService.dataVerify(reqParQO);
            if (result.getCode().isException()) {
                return result;
            }
            // 3、数据解析。
            result = dataService.setBusDataJson(reqParQO);
            // 4、数据校验未通过,或者数据解析失败,不执行业务方法,记录错误日志后直接返回错误信息
            if (result.getCode().isException()) {
                clientLog.info("[{}]return data <<< {}", methodName, result);
                return result;
            }
        }
        return null;
    }
    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * 事务切面。。。暂时不用事务
     * @param pointcut
     * @param order
     * @return
     */
//    @Bean
//    @ConditionalOnProperty(prefix = "lxt.pointcut.service",name = "value")
    public AspectJExpressionPointcutAdvisor transactionAspect(@Value("${lxt.pointcut.service.value}") String pointcut
            ,@Value("${lxt.pointcut.service.order}") Integer order){
        DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.addTransactionalMethod("insert*", txAttr_REQUIRED);
        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("remove*", txAttr_REQUIRED);
        source.addTransactionalMethod("modify*", txAttr_REQUIRED);
        source.addTransactionalMethod("modify*", txAttr_REQUIRED);
        source.addTransactionalMethod("test*", txAttr_REQUIRED);


        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);

        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(pointcut);
        advisor.setOrder(order);
        advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
        return advisor;
    }

    /**
     *
     * 动态数据源切换
     * @param pointcut
     * @param order
     * @return
     */
    @Bean
//    @ConditionalOnProperty(prefix = "lxt.pointcut.service",name = "is-dynamic-db",havingValue ="true")
    public AspectJExpressionPointcutAdvisor dynamicDBAspect(@Value("${lxt.pointcut.service.value}") String pointcut
            ,@Value("${lxt.pointcut.service.order}") Integer order){
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(pointcut);
        advisor.setOrder(order-1);
        advisor.setAdvice((MethodInterceptor) invocation -> {
            Method method = invocation.getMethod();
            if (method.isAnnotationPresent(MyDataSource.class)) {
                DataSourceHolder.set(method.getAnnotation(MyDataSource.class).value());
            } else {
                //当其他数据源操作完后,数据源不会自动变为默认数据源,需要在这里更改
                DataSourceHolder.set(DataSourceEnum.DEFAULT);
            }
            Object result=invocation.proceed();
            DataSourceHolder.clear();
            return result;
        });
        return advisor;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值