自定义注解浅谈及结合AOP实现操作记录

1、什么是注解?

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。它本身并不起任何作用,可以说有它没它都不影响程序的正常运行,注解的作用在于注解的处理程序,注解处理程序通过捕获被注解标记的代码然后进行一些处理,这就是注解工作的方式。

2、注解的作用?

知道了什么是注解,那么他的作用又是什么呢?

因为注解的不同,其作用也会大不一样,但是基本都是一下几点:

1、在编译时或程序执行时运行特定的方法

2、用来充当注释的作用(仅仅是一个文字的说明)  如@Deprecated表示已过期,不再建议使用

3、用来做代码的检测(验证) ,即检测此方法是否是一个重写的如@Override。

4、可以携带一些信息(内容)   比如以往我们可以使用文件.properties.xml注解来携带信息

3、注解注意事项

1、注解修饰只能是public 默认为public(即不写)

2、注解只支持 基本数据类型(int,byte,short,long,float,double,char,boolean)、String 、class、enum及以上的数组类型

4、元注解修饰自定义注解

1、@Target
ElementType.TYPE    应用于类、接口(包括注解类型)、枚举
ElementType.FIELD    应用于属性(包括枚举中的常量)
ElementType.METHOD    应用于方法
ElementType.PARAMETER    应用于方法的形参
ElementType.CONSTRUCTOR    应用于构造函数
ElementType.LOCAL_VARIABLE    应用于局部变量
ElementType.ANNOTATION_TYPE    应用于注解类型
ElementType.PACKAGE    应用于包
ElementType.TYPE_PARAMETER    1.8版本新增,应用于类型变量)
ElementType.TYPE_USE    1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

2、@Retention

Java源文件阶段(RetentionPolicy.SOURCE);

编译到class文件阶段(RetentionPolicy.CLASS);

运行期阶段(RetentionPolicy.RUNTIME)。

3、@Inherited

使用该注解其@target类型只能为ElementType.TYPE,其含义使用该注解的注解,在修饰其他类时,他的子类也会自动继承这个注解。

4、@Repeatable

jdk1.8引入 ,表示被修饰的注解可以重复应用标注 ,需要定义注解和容器注解

5、@Documented

这个注解可以被javadoc工具解析,形成帮助文档     
        idea生成javadoc的方式:
            顶行【Tools】-->【Generate javaDoc...】 -->
            【选择输出路径】+【在Other command line arguments中添加[-encoding utf-8 -charset utf-8]】   

5、注解的使用

1、创建自定义注解

@Target(ElementType.METHOD)//注解放置的目标位置即方法级别
@Retention(RetentionPolicy.RUNTIME)//注解在哪个阶段执行
@Documented
public @interface TestInterface {
    // 操作模块
    String operModul() default "";

    // 操作类型
    String operType() default "";

    // 操作说明
    String operDesc() default "";
}

2、结合AOP

首先创建一个AOP容器类 (PS: 使用@ASpect注解 需要提前导入AOP依赖)

@Aspect //标注该类是个aop容器
@Component //将该类注入到Spring容器中
public class TestAspect{

}
/**
 * TestAspect
 *
 * @author NSB
 * 
 */
@Component
@Aspect
public class TestAspect {

    //随便定义一个工具方法做切点用
    @Pointcut("@annotation(com.xinpu.aop.TestInterface)")// 匹配持有该注解的方法
    public void operLogPoinCut() {
    }

    /**
     * 
     *
     * @param joinPoint 方法的执行点
     * @param result    方法返回值
     * @throws Throwable
     */
    //执行完operLogPoincut方法后执行
    @AfterReturning(returning = "result", value = "operLogPoinCut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {
        //将返回值转换为map集合
        Map<String,Object> map = (Map<String, Object>) JSONObject.toJSON(result);
        map.forEach((x,y)-> System.out.println(map.get(x).toString()));
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        TestInterface annotation = method.getAnnotation(TestInterface.class);
        //输出注解中参数的属性
        System.out.println(annotation.toString());
    }
}

PS: @Pointcut

  • execution():用于匹配方法执行的连接点

  • args(): 用于匹配当前执行的方法传入的参数为指定类型的执行方法

  • this(): 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;

  • target(): 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

  • within(): 用于匹配指定类型内的方法执行;

  • @args():于匹配当前执行的方法传入的参数持有指定注解的执行;

  • @target():用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;

  • @within():用于匹配所以持有指定注解类型内的方法;

  • @annotation:用于匹配当前执行方法持有指定注解的方法;

3、创建一个测试类 

/**
 * TestController
 *
 * @author NSB
 *
 */
@RequestMapping("test")
@RestController
public class TestController {


    @RequestMapping("testZJ")
    @TestInterface(operModul="这是Modul",operType="这是Type",operDesc="这是Desc")
    public Map<String,String> testZJ(){
        Map<String,String> map = new HashMap();
        map.put("这是key1","这是结果1");
        map.put("这是key2","这是结果2");
        return map;
    }
}

运行postman看执行结果

INFOInitializing Spring DispatcherServlet 'dispatcherServlet'
INFOInitializing Servlet 'dispatcherServlet'
INFOCompleted initialization in 14 ms
这是结果1 //注解中map循环的输出  可以看出使用该注解在带偶用之后是可以获取到返回值的
这是结果2
//也是可以获取到自定义注解中三个参数的值
@com.xinpu.aop.TestInterface(operType=这是Type, operModul=这是Modul, operDesc=这是Desc)

通过以上可以发现,我们可以轻松的获取到返回值,并且可以在方法中随便写自己想要执行的逻辑,那么只需要把方法内的逻辑改变成往数据库插入你想要的参数就可以轻松的实现包括操作记录在内的多种功能。

OK,本次分享到此就结束了,码字不易感谢三连支持!!!

有什么疑问的话,可以在评论区提问,看到的话会第一时间回答。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Java中,我们可以使用自定义注解实现AOP(面向切面编程)。AOP是一种编程范型,它允许开发者在程序运行时动态地将代码切入到已有代码的特定位置。 下面是一个简单的示例,演示如何使用自定义注解实现AOP。 首先,我们需要定义一个自定义注解: ``` @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Loggable { } ``` 这个注解用来标记需要记录日志的方法。它的@Target注解指定了它只能用于方法上,@Retention注解指定了它的生命周期是运行时。 接下来,我们创建一个切面类,用来实现AOP的逻辑: ``` @Aspect @Component public class LoggingAspect { @Before("@annotation(com.example.Loggable)") public void logMethodCall(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("Method " + methodName + " called"); } } ``` 这个类使用Spring AOP框架提供的@Aspect注解来标记它是一个切面类。它的@Before注解指定了它要在被@Loggable注解标记的方法之前执行。JoinPoint参数包含了被拦截的方法的信息,我们可以从中获取方法名等信息。 最后,在需要记录日志的方法上加上@Loggable注解即可: ``` @Component public class MyService { @Loggable public void doSomething() { // do something } } ``` 当doSomething()方法被调用时,LoggingAspect中的logMethodCall()方法会被执行,记录方法调用信息。 这就是使用自定义注解实现AOP的基本步骤。当然,实际应用中会更加复杂,需要更多的切面逻辑和注解参数等。但是这个简单的示例可以帮助你理解如何使用自定义注解实现AOP

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值