zoukankan      html  css  js  c++  java
  • Spring切面编程实践【原创】

    定义

    什么叫Spring面向切面编程(AOP),请自行百度,这边就不做详细介绍了。

    场景

    有两个对象,字典和工程信息Bean,每次新增或修改对象时,记录新增和修改的时间。

    基类定义

    package myTest.entity;
    
    import lombok.Data;
    
    import java.time.LocalTime;
    
    /**
     * entity基类
     */
    @Data
    public class BaseEntity {
        private Long id;
        private LocalTime createTime;
        private LocalTime updateTime;
    }

    子类定义

    package myTest.entity;
    
    import lombok.Data;
    
    /**
     * 字典信息
     */
    @Data
    public class DictEntity extends BaseEntity{
        private String key;
        private String value;
    }
    package myTest.entity;
    
    import lombok.Data;
    
    /**
     * 项目信息
     */
    @Data
    public class ProjectEntity extends BaseEntity {
        private String projectName;
    }

    注:这边使用了lombok,不熟悉的同学可以查看https://www.cnblogs.com/meituan/p/10510889.html

    常规做法

    service基类

    package myTest.service;
    
    
    public interface BaseService<T> {
        void save(T entity);
        void update(T entity);
    }

    字典Service实现

    package myTest.service;
    
    import myTest.entity.DictEntity;import org.springframework.beans.factory.annotation.Autowired;
    
    import java.time.LocalTime;
    
    public class DictService implements BaseService<DictEntity> {
    
        @Autowired
        private DictDao dao;
    
        @Override
        public void save(DictEntity entity){
            entity.setCreateTime(LocalTime.now());
            entity.setUpdateTime(LocalTime.now());
            dao.save(entity);
        }
    
        @Override
        public void update(DictEntity entity){
            entity.setUpdateTime(LocalTime.now());
            dao.update(entity);
        }
    }

    工程Service实现

     

    package myTest.service;
    
    import myTest.entity.ProjectEntity;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.time.LocalTime;
    
    @Service
    public class ProjectService implements BaseService<ProjectEntity> {
    
        @Autowired
        private ProjectDao dao;
    
        @Override
        public void save(ProjectEntity entity){
            entity.setCreateTime(LocalTime.now());
            entity.setUpdateTime(LocalTime.now());
            dao.save(entity);
        }
    
        @Override
        public void update(ProjectEntity entity){
            entity.setUpdateTime(LocalTime.now());
            dao.update(entity);
        }
    
    }

    反思

    常规做法做了重复劳动工作,如果entity子类更多的话,重复劳动会更多,而且很不容易维护,这时候就可以用到Spring的切面编程思想。

    使用Spring AOP解决问题

    大致思路可以这样,当Service执行save和update方法的时候,定义一个切点,在执行到这个切点的时候,统一加入更新时间和新增时间的控制,一处增加,多处使用,省时省力,而且便于维护。上代码!

    • 首先,在pom文件中引入aspect依赖的jar包,如下

       

    <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.6.11</version>
            </dependency>
    • 其次,定义切点和前置通知

      

    package myTest;
    
    import myTest.entity.BaseEntity;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalTime;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 定义切点和前置通知,统一修改新增时间和修改时间
     */
    @Aspect
    @Component
    public class Asepect {
    
        @Pointcut("execution(* myTest.service.DictService.save*(..)) || execution(* myTest.service.DictService.update*(..)) || " +
                "execution(* myTest.service.ProjectService.save*(..)) || execution(* myTest.service.ProjectService.update*(..))")
        public void addAndUpdatePointCut(){}
    
        @Before("addAndUpdatePointCut()")
        public void before(JoinPoint joinPoint) {
            //获取方法名
            String mathName = joinPoint.getSignature().getName();
            //获取参数列表
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            for (Object o :
                    args) {
                if (o instanceof BaseEntity) {
                    ((BaseEntity) o).setUpdateTime(LocalTime.now());
                    if (mathName.startsWith("save")) {
                        ((BaseEntity) o).setCreateTime(LocalTime.now());
                    }
                }
            }
        }
    
    }

    就这样两个简单的步骤,就可以解决原始方法带来的重复工作和不易维护的问题,是不是很爽?

    【纯手打,请多多支持,谢谢】

     

  • 相关阅读:
    面试题:垂直居中几种方法
    零碎记忆--随机
    v-model 和 :model 的区别
    Vue--keep-alive 理解
    vue 中 $route 和 $router 的区别
    Vue + Element UI 实现权限管理系统 前端篇(十):动态加载菜单
    Vue + Element UI 实现权限管理系统 前端篇(九):接口格式定义
    Vue + Element UI 实现权限管理系统 前端篇(八):管理应用状态
    Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装
    [2020牛客暑期多校训练营(第十场)C Decrement on the Tree]
  • 原文地址:https://www.cnblogs.com/meituan/p/10511843.html
Copyright © 2011-2022 走看看