一、说明

  项目中经常会有一些放在缓存中的公共字段需要进行填充,我们知道mybatis-plus很方便地可以实现公共字段填充。在这里我定义了一个字段填充的注解,当我们需要进行数据填充的时候只要在方法上打上注解,aop自动扫描该注解就可以实现字段填充的功能了。温故而知新,今天有空整理下最近学到的东西,在分享的时候顺带复习下最近学到的知识。

二、注解相关知识简介

  1、注解的定义:在java中使用@interface表示注解。四种元注解分别是@Retention、@Target、@Document、@Inherited。

  2、@Retention 表示注解的保留策略:

      @Retention(RetentionPolicy.SOURCE)   // 注解仅存在于源码中,会被编译器丢弃,不包含在class字节码文件中

      @Retention(RetentionPolicy.CLASS)      // 默认的保留策略,注解会被VM丢弃,在class字节码文件中存在,在运行时无法获得

      @Retention(RetentionPolicy.RUNTIME)  // VM将在运行期间保留注解,在class字节码文件中存在,在运行时可以通过机制读取注解的信息

  3、@Target 表示注解的作用目标(枚举 public enum ElementType)

      @Target(ElementType.TYPE)                           // 接口、类、枚举、注解

      @Target(ElementType.FIELD)                          // 字段、枚举的常量

      @Target(ElementType.METHOD)                     // 方法

      @Target(ElementType.PARAMETER)              // 方法参数

      @Target(ElementType.CONSTRUCTOR)        // 构造函数

      @Target(ElementType.LOCAL_VARIABLE)     // 局部变量

      @Target(ElementType.ANNOTATION_TYPE)  // 注解

      @Target(ElementType.PACKAGE)                   // 包

      /**

        * Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解

        * 新增两种类型注解,可以用在任何使用到类型的地方

      */

      @Target(ElementType.TYPE_PARAMETER)  //@since 1.8 表示该注解能写在类型参数的声明语句中

      @Target(ElementType.TYPE_USE)                 //@since 1.8 表示注解可以再任何用到类型的地方使用

  4、@Documented 表示注解包含在javadoc文档中  

  5、@Inherited 表示注解可以被继承,默认注解并没有继承于任何子类

三、Spring Aop简介

  AOP(Aspect Oriented Programming),即面向切面编程。

  1、横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。

  2、切面(aspect):切面是一个关注点的模块化,这个关注点可能是横切多个对象。类是对物体特征的抽象,切面就是对横切关注点的抽象。

  3、连接点(joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。

  4、切入点(pointcut):匹配连接点的断言,对连接点进行拦截的定义。

  5、通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。

    • 前置通知(Before):在目标方法或者说连接点被调用前执行的通知;
    • 后置通知(After):指在某个连接点完成后执行的通知;
    • 返回通知(After-returning):指在某个连接点成功执行之后执行的通知;
    • 异常通知(After-throwing):指在方法抛出异常后执行的通知;
    • 环绕通知(Around):指包围一个连接点通知,在被通知的方法调用之前和之后执行自定义的方法

  6、目标对象(Target):代理的目标对象。

  7、织入(weave):将切面应用到目标对象并导致代理对象创建的过程。

  8、引入(introduction):引入也被称为内部类型声明,声明额外的方法或者某个类型的字段。在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。

四、代码

  1、自定义注解 FillFields

package com.gongyu.annotation.FillFields;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 字段填充注解
* @author gongyu
* @date 20190920
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FillFields {
}

  2、Aop扫描注解填充字段(自定义一个试题类提供set/get方法)

package com.gongyu.filedAop.aop;

import java.lang.reflect;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; @Aspect
@Component
public class ServiceAop {

private final String POINT_CUT = "@annotation(com.gongyu.annotation.FillFields)";public ServiceAop() { @Pointcut(POINT_CUT)public void fillFiled() {
    }

    @Around("fillFiled()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long orgId = 111L;
long createdBy = 333L;
LocalDateTime createdTime = LocalDateTime.now();
     long version = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
Object[] args = pjp.getArgs();
Object object = args[0];
if (object != null) {
Class objectClass = object.getClass();
Field[] fs = objectClass.getDeclaredFields();
      for(Field f : fs) {
          // 设置访问权限
f.setAccessible(true);
         /*
          * 填充字段 orgId 有则取,没有则塞
          * Method method=null;
          */
if ("orgId".equals(f.getName())) {
            Method getOrgIdMethod=objectClass.getDeclaredMethod("getOrgId");
            Object o=getOrgIdMethod.invoke(object);
            if(o==null) {
              Method setOrgIdMethod = objectClass.getDeclaredMethod("setOrgId", long.class);
              setOrgIdMethod.invoke(object, orgId);
            }
}
          //填充字段 createdBy
          if(("createdBy").equals(f.getName())){
            Method createdByMethod=objectClass.getDeclaredMethod("setCreatedBy",long.class);
            createdByMethod.invoke(object,createdBy);
          }
         //填充字段 createdTime
         if(("createdTime").equals(f.getName())){
            Method createdTimeMethod=objectClass.getDeclaredMethod("setCreatedTime",LocalDateTime.class);
            createdTimeMethod.invoke(object,createdTime);
          }          //填充字段 version
         if(("version").equals(f.getName())){
            Method versionMethod=objectClass.getDeclaredMethod("setVersion",long.class);
            versionMethod.invoke(object,version);
         } } System.out.println("字段填充成功后=>" + object);
} return pjp.proceed();
}
}

SpringAop实现公共字段填充的更多相关文章

  1. SpringBoot-Mybatis_Plus学习记录之公共字段自动填充

    一.应用场景 平时在建对象表的时候都会有最后修改时间,最后修改人这两个字段,对于这些大部分表都有的字段,每次在新增和修改的时候都要考虑到这几个字段有没有传进去,很麻烦.mybatisPlus有一个很好 ...

  2. MybatisPlus自动填充公共字段的策略

    背景:数据库中多个表有时间字段,并且字段名一致 需求:该时间字段由MybatisPlus自动插入和更新,业务代码无需处理 方法: 一.创建基础实体[BaseEntity],定义需要处理的公共字段(创建 ...

  3. 如何自动填充SQL语句中的公共字段

    1. 前言 我们在设计数据库的时候一定会带上新增.更新的时间.操作者等审计信息. 之所以带这些信息是因为假如有一天公司的数据库被人为删了,尽管可能有数据库备份可以恢复数据.但是我们仍然需要追踪到这个事 ...

  4. 通信统计接口字段填充内容shell脚本

    现在通信行业上班,最麻烦的就是计算各个协议接口字段填充的内容是否正确.经历了小白似的一个个字段统计在到单个接口所有字段统计,然后到现在的多个接口一次统计.在大大节省了时间的同时,让自己有更充足的时间来 ...

  5. 【laravel54】如果开启了自带的时间戳(Y-h-m H:s:m),getInsertId一定要手动加上created_at 和 updated_at字段填充

    [laravel54]如果开启了自带的时间戳(Y-h-m H:s:m),getInsertId一定要手动加上created_at 和 updated_at字段填充

  6. EF中多表公共字段,以及设置EntityBase使所有实体类继承自定义类

    使用EF框架访问数据库时,如果某些表具有公共字段,例如在审核流程中,对于各类申请单资料的创建人.创建时间.修改人.修改时间,这些可能多表都需要的字段,如果在每个实体中进行赋值操作显然是类似和重复的,下 ...

  7. EXCEL中多级分类汇总空白字段填充

    使用场景,多级分类汇总后,在汇总的字段中显示空白,这样对我们直接取值做表带来十分不更(假像有5000条记录,1000条汇总项) 相关技术,INDIRECT函数,单元格定位功能. 在数据区域外任意一个单 ...

  8. SpringBoot与MybatisPlus整合之公用字段填充(十一)

    在实际开发中,适合用于记录创建人修改人 pom.xml <dependencies> <dependency> <groupId>org.springframewo ...

  9. 小书MybatisPlus第9篇-常用字段默认值自动填充

    本文为Mybatis Plus系列文章的第9篇,前8篇访问地址如下: 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总 ...

随机推荐

  1. Android lifecycle 使用详解

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/gdutxiaoxu/article/det ...

  2. .Net Mvc过滤器观察者模式记录网站报错信息

    基本介绍: 观察者模式是一种对象行为模式.它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.在观察者模式中,主题是通知的发布者,它发出通知时并不 ...

  3. Docker系列之AspNetCore Runtime VS .NetCore Runtime VS .NET Core SDK(四)

    前言 接下来我们就要慢慢步入在.NET Core中使用Docker的殿堂了,在开始之前如题,我们需要搞清楚一些概念,要不然看到官方提供如下一系列镜像,我们会一脸懵逼,不知道到底要使用哪一个. AspN ...

  4. 基础部分之System、Object、Calendar、StringBuffer

    System.out.println(obj)和 System.out.println(obj.toString())区别 public static void main(String[] args) ...

  5. 实战SpringCloud响应式微服务系列教程(第四章)

    接上一篇: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 实战SpringCloud响应式微服务系列教程(第三章) 1.1.4 引 ...

  6. 本地图片上传到GitHub,MarkDown使用Github图片地址

    最近在学习用markdown编辑器,我是直接用有道云笔记编辑的,感觉真的好好用,编辑了一半的博客,可以按样式保存在云笔记中,我再也不会忘记写博客了~~ 但是在编辑博客的时候发现了一个问题,那就是本地图 ...

  7. Leetcode之深度优先搜索&回溯专题-638. 大礼包(Shopping Offers)

    Leetcode之深度优先搜索&回溯专题-638. 大礼包(Shopping Offers) 深度优先搜索的解题详细介绍,点击 在LeetCode商店中, 有许多在售的物品. 然而,也有一些大 ...

  8. python decode encode 解码与编码问题

    python 解码与编码问题 1.decode 俗称解码,把编码解码成unicode,例如一个字符串变量 str 是utf-8编码,使用str.decode('utf-8')  ,就是把utf-8编码 ...

  9. 从零开始搭建Java开发环境第四篇:精选IDEA中十大提高开发效率的插件!

    Lombok 知名的插件,无需再写那么多冗余的get/set代码 JRebel 热部署插件 alibaba java coding guide 阿里巴巴代码规范插件,自动检查代码规范问题 [在这里插入 ...

  10. 解决vs2013中MVC/WebApi不显示添加区域菜单选项

    在构建项目过程中,安装各种package或者卸载的过程中,导致了添加区域菜单选项不显示,导致后面无法添加区域. 在网上查找各种资料,发现原来是工程文件(项目名.csproj)缺少mvc引用. 工程文件 ...