aop+自定义注解实现日志功能(参数前后变化)

2 篇文章 0 订阅

aop+自定义注解实现日志功能(参数前后变化)

依赖

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.18</version>
        </dependency>
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.21</version>
        </dependency>
        <!-- SpringBoot 核心包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

package com.aisino.project.monitor.domain;

import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.aisino.framework.aspectj.lang.annotation.Excel;
import com.aisino.framework.aspectj.lang.annotation.Excel.ColumnType;
import com.aisino.framework.web.domain.BaseEntity;

/**
 * 操作日志记录表 oper_log
 *
 * @author aisino
 */
public class SysOperLog extends BaseEntity {
    private static final long serialVersionUID = 1L;

    /**
     * 日志主键
     */
    @Excel(name = "操作序号" , cellType = ColumnType.NUMERIC)
    private Long operId;

    /**
     * 操作模块
     */
    @Excel(name = "操作模块")
    private String title;

    /**
     * 业务类型(0其它 1新增 2修改 3删除)
     */
    @Excel(name = "业务类型" , readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")
    private Integer businessType;

    /**
     * 业务类型数组
     */
    private Integer[] businessTypes;

    /**
     * 请求方法
     */
    @Excel(name = "请求方法")
    private String method;

    /**
     * 请求方式
     */
    @Excel(name = "请求方式")
    private String requestMethod;

    /**
     * 操作类别(0其它 1后台用户 2手机端用户)
     */
    @Excel(name = "操作类别" , readConverterExp = "0=其它,1=后台用户,2=手机端用户")
    private Integer operatorType;

    /**
     * 操作人员
     */
    @Excel(name = "操作人员")
    private String operName;

    /**
     * 部门名称
     */
    @Excel(name = "部门名称")
    private String deptName;

    /**
     * 请求url
     */
    @Excel(name = "请求地址")
    private String operUrl;

    /**
     * 操作地址
     */
    @Excel(name = "操作地址")
    private String operIp;

    /**
     * 操作地点
     */
    @Excel(name = "操作地点")
    private String operLocation;

    /**
     * 请求参数
     */
    @Excel(name = "请求参数")
    private String operParam;


    /**
     * 原有请求参数
     */
    @Excel(name = "原有请求参数")
    private String operInitParam;

    /**
     * 返回参数
     */
    @Excel(name = "返回参数")
    private String jsonResult;

    /**
     * 操作状态(0正常 1异常)
     */
    @Excel(name = "状态" , readConverterExp = "0=正常,1=异常")
    private Integer status;

    /**
     * 错误消息
     */
    @Excel(name = "错误消息")
    private String errorMsg;

    /**
     * 操作时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "操作时间" , width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date operTime;

    public String getOperInitParam() {
        return operInitParam;
    }

    public void setOperInitParam(String operInitParam) {
        this.operInitParam = operInitParam;
    }

    public Long getOperId() {
        return operId;
    }

    public void setOperId(Long operId) {
        this.operId = operId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Integer getBusinessType() {
        return businessType;
    }

    public void setBusinessType(Integer businessType) {
        this.businessType = businessType;
    }

    public Integer[] getBusinessTypes() {
        return businessTypes;
    }

    public void setBusinessTypes(Integer[] businessTypes) {
        this.businessTypes = businessTypes;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getRequestMethod() {
        return requestMethod;
    }

    public void setRequestMethod(String requestMethod) {
        this.requestMethod = requestMethod;
    }

    public Integer getOperatorType() {
        return operatorType;
    }

    public void setOperatorType(Integer operatorType) {
        this.operatorType = operatorType;
    }

    public String getOperName() {
        return operName;
    }

    public void setOperName(String operName) {
        this.operName = operName;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getOperUrl() {
        return operUrl;
    }

    public void setOperUrl(String operUrl) {
        this.operUrl = operUrl;
    }

    public String getOperIp() {
        return operIp;
    }

    public void setOperIp(String operIp) {
        this.operIp = operIp;
    }

    public String getOperLocation() {
        return operLocation;
    }

    public void setOperLocation(String operLocation) {
        this.operLocation = operLocation;
    }

    public String getOperParam() {
        return operParam;
    }

    public void setOperParam(String operParam) {
        this.operParam = operParam;
    }

    public String getJsonResult() {
        return jsonResult;
    }

    public void setJsonResult(String jsonResult) {
        this.jsonResult = jsonResult;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public Date getOperTime() {
        return operTime;
    }

    public void setOperTime(Date operTime) {
        this.operTime = operTime;
    }
}

自定义注解

package com.aisino.framework.aspectj.lang.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.aisino.framework.aspectj.lang.enums.BusinessType;
import com.aisino.framework.aspectj.lang.enums.OperatorType;

/**
 * 自定义操作日志记录注解
 *
 * @author aisino
 *
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * 模块
     */
    public String title() default "";

    /**
     * 功能
     */
    public BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    public OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    public boolean isSaveRequestData() default true;

    /**
     * 是否保存响应的参数
     */
    public boolean isSaveResponseData() default true;

    /**查询的bean名称*/
    String serviceClass() default "";

    /**查询单个详情的bean的方法*/
    String queryMethod() default "";

    /**查询详情的参数类型*/
    String parameterType() default "";

    /**从页面参数中解析出要查询的id,
     * 如域名修改中要从参数中获取customerDomainId的值进行查询
     */
    String parameterKey() default "";

}

获取springBean容器

package com.aisino.framework.aspectj;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


/**
 * 获取spring容器,以访问容器中定义的其他bean
 *  xiang
 *  MOSTsView 3.0 2009-11-16
 */
@Component
public class SpringContextUtil implements ApplicationContextAware{

    private static ApplicationContext   applicationContext;

    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     */
    public void setApplicationContext(ApplicationContext applicationContext){
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }

    /**
     * 获取对象
     * @return  Object 一个以所给名字注册的bean的实例 (service注解方式,自动生成以首字母小写的类名为bean name)
     */
    public static Object getBean(String name) throws BeansException{
        return applicationContext.getBean(name);
    }
}

编写aop前置 后置通知 (里面细节不全 需要自己填写)

package com.aisino.framework.aspectj;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.aisino.common.utils.StringUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import com.alibaba.fastjson.JSON;
import com.aisino.common.enums.HttpMethod;
import com.aisino.common.utils.SecurityUtils;
import com.aisino.common.utils.ServletUtils;
import com.aisino.common.utils.ip.IpUtils;
import com.aisino.framework.aspectj.lang.annotation.Log;
import com.aisino.framework.aspectj.lang.enums.BusinessStatus;
import com.aisino.framework.manager.AsyncManager;
import com.aisino.framework.manager.factory.AsyncFactory;
import com.aisino.framework.security.LoginUser;
import com.aisino.project.monitor.domain.SysOperLog;

/**
 * 操作日志记录处理
 *
 * @author aisino
 */
@Aspect
@Component
public class LogAspect
{
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    private static String ORDERJSON =null;


    /**
    * @desc : 处理前执行
    * @Return :
    * @Author : Jerry
    * @Date : Created in 2022-9-21 9:27
    **/
    //前置通知, 在方法执行之前执行
    @Before(value = "@annotation(controllerLog)")
    public void before(JoinPoint joinPoint, Log controllerLog) {
        //常见日志实体对象
        // 拦截的实体类,就是当前正在执行的controller
        Object target = joinPoint.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = joinPoint.getSignature().getName();
        // 拦截的放参数类型
        Signature sig = joinPoint.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        // 判断请求类型
        // 判断参数类型格式-对应取出里面key值
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            System.out.println(e1);
        } catch (SecurityException e1) {
            System.out.println(e1);
        }
        Log systemlog = method.getAnnotation(Log.class);
        String queryMethod = systemlog.queryMethod();
        //查询
        if (methodName.equals("query")){

        }
        //新增
        if (methodName.equals("add")){
            ORDERJSON = "新增方法暂无旧数据";
        }
        //删除
        if (methodName.equals("remove")){
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                Object paramsObj = args[i];
                String param = judgeType(paramsObj);
                //批量删除
                if (param.indexOf("[]")!=-1){
                    if (param.equals("Long[]")){
                        Long[] longs = (Long[])paramsObj;
                        for (Long l : longs){
                            Object data = getOperateBeforeData(controllerLog.parameterType(), controllerLog.serviceClass(), queryMethod, l.toString());
                            JSONObject jsonObject = (JSONObject) JSON.toJSON(data);
                            ORDERJSON +=jsonObject;
                        }
                    }
                }else{
                //单次删除
                    Object data = getOperateBeforeData(controllerLog.parameterType(), controllerLog.serviceClass(), queryMethod, paramsObj.toString());
                    JSONObject jsonObject = (JSONObject) JSON.toJSON(data);
                    ORDERJSON = jsonObject.toString();
                }

            }
        }
        //导入
        if (methodName.equals("export")){
            ORDERJSON = "导入方法暂无旧数据";
        }
        //编辑
        if (methodName.equals("edit")){
            Object[] args = joinPoint.getArgs();
            Object outprint ="";
            for (int i = 0; i < args.length; i++) {
                Object paramsObj = args[i];
                Map<String,Object> map = JSONObject.parseObject(JSON.toJSONString(paramsObj));
                outprint = map.get(controllerLog.parameterKey());
            }
            if (!ObjectUtils.isEmpty(outprint)){
                Object data = getOperateBeforeData(controllerLog.parameterType(), controllerLog.serviceClass(), queryMethod, outprint.toString());
                JSONObject jsonObject = (JSONObject) JSON.toJSON(data);
                ORDERJSON = jsonObject.toString();
            }
        }

    }
    /**
     * @param obj 需要判断类型的值
     */
    public String judgeType(Object obj){
        if (obj instanceof Boolean){
            //进行你的逻辑处理
            return "Boolean";
        }else if (obj instanceof Byte){
            return "Byte";
        }else if (obj instanceof Character){
            return "Character";
        }else if (obj instanceof Short){
            return "Short";
        }else if (obj instanceof Integer){
            return "Integer";
        }else if (obj instanceof Long){
            return "Long";
        }else if (obj instanceof Float){
            return "Float";
        }else if (obj instanceof Double){
            return "Double";
        }else if (obj instanceof String){
            return "String";
        }else if (obj instanceof Date){
            return "Date";
        }else if (obj instanceof Array){
            return "Array";
        }else if (obj instanceof Map){
            return "Map";
        }else if (obj instanceof List){
            return "List";
        }else if (obj instanceof BigDecimal){
            return "BigDecimal";
        }else if (obj instanceof BigInteger){
            return "BigInteger";
        }else if (obj instanceof Stack){
            return "Stack";
        }else if (obj instanceof Long[]){
            return "Long[]";
        }else {
            return "未知类型--"+obj.getClass();
        }
    }

    /**
     *
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param paramType:参数类型
     * @param serviceClass:bean名称
     * @param queryMethod:查询method
     * @param value:查询id的value
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Object getOperateBeforeData(String paramType,String serviceClass,String queryMethod,String value){
        Object obj = new Object();
        //在此处解析请求的参数类型,根据id查询数据,id类型有四种:int,Integer,long,Long
        if(paramType.equals("int")){
            int id = Integer.parseInt(value);
            Method  mh = ReflectionUtils.findMethod(SpringContextUtil.getBean(serviceClass).getClass(), queryMethod,Long.class );
            //传入的id类型与bean里面的参数类型需要保持一致
            obj = ReflectionUtils.invokeMethod(mh,  SpringContextUtil.getBean(serviceClass),id);

        }else if(paramType.equals("Integer")){
            Integer id = Integer.valueOf(value);
            Method  mh = ReflectionUtils.findMethod(SpringContextUtil.getBean(serviceClass).getClass(), queryMethod,Long.class );
            //传入的id类型与bean里面的参数类型需要保持一致
            obj = ReflectionUtils.invokeMethod(mh,  SpringContextUtil.getBean(serviceClass),id);

        }else if(paramType.equals("long")){
            long id = Long.parseLong(value);
            Method  mh = ReflectionUtils.findMethod(SpringContextUtil.getBean(serviceClass).getClass(), queryMethod,Long.class );
            //传入的id类型与bean里面的参数类型需要保持一致
            obj = ReflectionUtils.invokeMethod(mh,  SpringContextUtil.getBean(serviceClass),id);

        }else if(paramType.equals("Long")){
            Long id = Long.valueOf(value);
            Method  mh = ReflectionUtils.findMethod(SpringContextUtil.getBean(serviceClass).getClass(), queryMethod,Long.class );
            //传入的id类型与bean里面的参数类型需要保持一致
            obj = ReflectionUtils.invokeMethod(mh,  SpringContextUtil.getBean(serviceClass),id);
        }
        return obj;
    }

    /**
     * 获取当前执行的方法
     *
     * @param joinPoint  连接点
     * @param methodName 方法名称
     * @return 方法
     */
    private Method currentMethod(JoinPoint joinPoint, String methodName) {
        /**
         * 获取目标类的所有方法,找到当前要执行的方法
         */
        Method[] methods = joinPoint.getTarget().getClass().getMethods();
        Method resultMethod = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                resultMethod = method;
                break;
            }
        }
        return resultMethod;
    }
    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
    {
        handleLog(joinPoint, controllerLog, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e 异常
     */
    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
    {
        handleLog(joinPoint, controllerLog, e, null);
    }

    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
    {
        try
        {
            // 获取当前的用户
            LoginUser loginUser = SecurityUtils.getLoginUser();
            // *========数据库日志=========*//
            SysOperLog operLog = new SysOperLog();
            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            // 请求的地址
            String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
            operLog.setOperIp(ip);
            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
            if (loginUser != null)
            {
                operLog.setOperName(loginUser.getUsername());
            }

            if (e != null)
            {
                operLog.setStatus(BusinessStatus.FAIL.ordinal());
                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 设置请求方式
            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
            operLog.setOperInitParam(ORDERJSON);

            // 处理设置注解上的参数
            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
            // 保存数据库
            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
            ORDERJSON = "";
        }
        catch (Exception exp)
        {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param log 日志
     * @param operLog 操作日志
     * @throws Exception
     */
    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
    {
        // 设置action动作
        operLog.setBusinessType(log.businessType().ordinal());
        // 设置标题
        operLog.setTitle(log.title());
        // 设置操作人类别
        operLog.setOperatorType(log.operatorType().ordinal());
        // 是否需要保存request,参数和值
        if (log.isSaveRequestData())
        {
            // 获取参数的信息,传入到数据库中。
            setRequestValue(joinPoint, operLog);
        }
        // 是否需要保存response,参数和值
        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
        {
            operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
        }
    }

    /**
     * 获取请求的参数,放到log中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
    {
        String requestMethod = operLog.getRequestMethod();
        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
        {
            String params = argsArrayToString(joinPoint.getArgs());
            Map maps = (Map)JSON.parse(params);
            Map hashMap = new HashMap<>();
            for (Object map : maps.entrySet()){
                if (((Map.Entry)map).getKey().equals("objJson")){
                    operLog.setOperInitParam(((Map.Entry)map).getValue().toString());
                }else{
                    hashMap.put(((Map.Entry)map).getKey(),((Map.Entry)map).getValue());
                }
            }
            String json = JSONObject.toJSONString(hashMap);
            operLog.setOperParam(StringUtils.substring(json, 0, 2000));
        }
        else
        {
            Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
        }
    }

    /**
     * 参数拼装
     */
    private String argsArrayToString(Object[] paramsArray)
    {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0)
        {
            for (Object o : paramsArray)
            {
                if (StringUtils.isNotNull(o) && !isFilterObject(o))
                {
                    try
                    {
                        Object jsonObj = JSON.toJSON(o);
                        params += jsonObj.toString() + " ";
                    }
                    catch (Exception e)
                    {
                    }
                }
            }
        }
        return params.trim();
    }

    /**
     * 判断是否需要过滤的对象。
     *
     * @param o 对象信息。
     * @return 如果是需要过滤的对象,则返回true;否则返回false。
     */
    @SuppressWarnings("rawtypes")
    public boolean isFilterObject(final Object o)
    {
        Class<?> clazz = o.getClass();
        if (clazz.isArray())
        {
            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
        }
        else if (Collection.class.isAssignableFrom(clazz))
        {
            Collection collection = (Collection) o;
            for (Object value : collection)
            {
                return value instanceof MultipartFile;
            }
        }
        else if (Map.class.isAssignableFrom(clazz))
        {
            Map map = (Map) o;
            for (Object value : map.entrySet())
            {
                Map.Entry entry = (Map.Entry) value;
                return entry.getValue() instanceof MultipartFile;
            }
        }
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
                || o instanceof BindingResult;
    }
}

controller层调用
serviceClass:填写自己在修改、删除之前查询 需要调用的 service
queryMethod:填写自己 对应serve层根据id查询的方法
parameterType:填写 自己 主键 id 类型
parameterKey:填写 自己 主键昵称
另外 需要在自己的实现层标明 service名称,不然找不到
@Service(“ISysOrganService”)

   /**
     * 删除组织管理
     */
    @Log(title = "组织管理", businessType = BusinessType.DELETE,
            serviceClass="ISysOrganService",
            queryMethod="selectSysOrganById",
            parameterType="Long",
            parameterKey="id")
	@DeleteMapping("/{id}")
    public AjaxResult remove(@PathVariable Long id)
    {
        return sysOrganService.deleteSysOrganById(id);
    }

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP(面向切面编程)是Spring框架中的一个组件,它允许您以一种声明性的方式来处理横切关注点(如事务管理,日志记录等)。 通过使用AOP,可以将这些关注点从应用程序的主体中分离出来,从而实现代码的复用和灵活性。 在使用Spring框架中实现数据源的切换时,可以使用自定义注解的形式来实现。首先,首先在应用程序的主体中定义两个数据源。 然后,可以定义一个自定义注解,用于标识哪些方法应该使用哪个数据源。例如,使用“@Primary”注解标记主要数据源,使用“@Secondary”注解标记辅助数据源。 然后,在Spring配置中定义一个AOP切面,该切面使用上述自定义注解来切换数据源。下面是这种方法的一个示例: ```java @Aspect @Component public class DataSourceAspect { @Around("@annotation(Primary)") public Object primaryDataSource(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { // 切换到主要数据源 DynamicDataSourceContextHolder.setDataSource(DynamicDataSourceContextHolder.DATA_SOURCE_PRIMARY); try { return proceedingJoinPoint.proceed(); } finally { // 切换回默认数据源 DynamicDataSourceContextHolder.clearDataSource(); } } @Around("@annotation(Secondary)") public Object secondaryDataSource(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { // 切换到辅助数据源 DynamicDataSourceContextHolder.setDataSource(DynamicDataSourceContextHolder.DATA_SOURCE_SECONDARY); try { return proceedingJoinPoint.proceed(); } finally { // 切换回默认数据源 DynamicDataSourceContextHolder.clearDataSource(); } } } ``` 在上面的代码中,我们可以看到“@Around”注解被用于定义一个环绕通知,该通知基于使用“@Primary”或“@Secondary”注解的方法进行拦截。 在方法执行之,我们使用“DynamicDataSourceContextHolder”来将数据源设置为主要或辅助数据源。 在方法执行完成之后,我们将数据源切换回默认数据源。 最后,我们可以将“@Primary”和“@Secondary”注解带到相应的方法上,以切换不同的数据源,例如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override @Primary public User getUserById(long id) { return userDao.getUserById(id); } @Override @Secondary public List<User> getAllUsers() { return userDao.getAllUsers(); } } ``` 在上面的代码中,我们可以看到“@Primary”注解被用于getUserById()方法,表示这个方法应该从主要数据源中读取数据。相反,getAllUsers()方法被标记为“@Secondary”注解,表示这个方法应该从辅助数据源中读取数据。 通过这种方式,我们可以很容易地切换应用程序中的不同数据源,并且代码的重复率很低。这种方法适用于需要在应用程序的不同部分使用不同数据源的多租户应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值