自定义注解:让代码更加简洁优雅

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 自定义注解:让代码更加简洁优雅

自定义注解:让代码更加简洁优雅

七:总结

一:前言

在 Java 开发中,注解是一种非常常见的语言特性。Java 自带了一些常用的注解,如 @Override、@Deprecated 等。但有时候我们需要自己定义一些注解,来标注我们自己的业务逻辑,或者是对第三方库的使用进行规范等。


自定义注解是一种非常强大的工具,可以让我们的代码更加简洁、优雅、易读,提高代码的可维护性。本文将通过一个例子来介绍如何自定义注解。


二:Java内什么是注解

在Java中,注解(Annotation)是一种元数据,它提供了关于程序代码的额外信息。注解可以用来描述类、方法、变量、参数等元素,它们不会直接影响程序代码的运行,但可以提供给编译器、解释器或其他工具使用。

注解使用@符号作为标记,后面紧跟着注解的名称和一组参数。例如,@Override注解用于指示方法是覆盖了父类中的方法。

Java中的注解有很多种类型,包括预定义的注解,如@Override和@Deprecated,还有自定义注解。自定义注解可以通过定义一个@interface来创建,并且可以指定一些元素来描述注解的属性。

注解在Java编程中的应用非常广泛,例如用于标记测试用例、配置文件、RESTful服务等等。通过注解,可以使程序代码更加简洁、清晰,同时也可以提高代码的可维护性和可读性。

三:打印日志准备

在我们的日常开发中,经常需要打印日志,以便我们能够了解程序的运行情况。我们可以使用 Java 自带的日志库 java.util.logging,也可以使用第三方的日志库,如 Log4j、Slf4j 等。


无论我们使用什么日志库,都需要写出类似下面的代码:

public class MyClass {
    private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
    public void myMethod() {
        logger.debug("debug message");
        logger.info("info message");
        logger.warn("warn message");
        logger.error("error message");
    }
}

每个方法都需要写出类似的代码,这显然很冗长。我们可以使用自定义注解来简化这个过程。

四:自定义注解

4.1 定义注解代码

首先我们需要定义一个注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value();
}

这个注解的作用是在方法上打印日志,value() 方法返回需要打印的日志信息。


4.2 注解代码重点解释

1.@Target注解用于指定其他注解可以应用于哪些程序元素,它本身是一个元注解(Meta-Annotation),用于修饰其他注解。它的参数是一个ElementType数组,表示可以使用该注解的程序元素的类型。

2.@Retention注解用于指定注解的保留策略,即该注解是否会被编译器保留在class文件中,并且能否在运行时通过反射获取到。


在Java中,有三种保留策略,分别为:

SOURCE:该注解仅在源代码中保留,编译器会将其丢弃,不会保留到class文件中。

CLASS:该注解会被保留到class文件中,但不会被加载到内存中,因此无法在运行时获取到。

RUNTIME:该注解会被保留到class文件中,并且可以在运行时通过反射获取到。

4.3 使用此注解

接下来,我们可以在需要打印日志的方法上使用这个注解:

public class MyClass {
    private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
    @Log("myMethod start")
    public void myMethod() {
        // do something
    }
}

当我们调用 myMethod() 方法时,注解 @Log 将自动打印日志。这样,我们就不需要在每个方法中手动写出日志打印的代码了。


五:AOP切面实现读取注解

关于aop的知识大家可以看我的这篇文章:利用Spring框架实现横向关注点

下面是一个简单的实现。我们需要定义一个切面,来处理这个注解:

@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
   // 使用@Around注解,指定拦截含有@Log注解的方法
@Around("@annotation(com.example.Log)")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    // 获取方法签名和方法对象
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    // 获取@Log注解的值
    Log logAnnotation = method.getAnnotation(Log.class);
    String logMsg = logAnnotation.value();
    // 记录方法开始的日志信息
    logger.info("{}.{} - start: {}", joinPoint.getTarget().getClass().getSimpleName(), method.getName(), logMsg);
    // 执行原方法
    Object result = joinPoint.proceed();
    // 记录方法结束的日志信息
    logger.info("{}.{} - end", joinPoint.getTarget().getClass().getSimpleName(), method.getName());
    // 返回方法的执行结果
    return result;
}
}

这个切面使用了 AspectJ 的注解机制,使用 @Aspect 注解标注这是一个切面,使用 @Component 注解将这个切面注入到 Spring 容器中。


@Around 注解用于定义一个环绕通知,可以在方法执行前后进行一些操作。这个环绕通知中,我们通过 @annotation(com.example.Log) 注解来获取方法上的 @Log 注解,并从中获取日志信息。然后在方法执行前后打印日志。


六:具体使用

我们需要在 Spring 配置文件中开启注解扫描,以便 Spring 能够扫描到我们定义的注解和切面:

<context:component-scan base-package="com.example" />

然后我们就可以在代码中使用我们定义的 @Log 注解了:

public class MyClass {
    @Log("myMethod start")
    public void myMethod() {
        // do something
    }
}

当我们调用 myMethod() 方法时,注解 @Log 将自动打印日志。


七:总结

自定义注解是一种非常强大的工具,可以让我们的代码更加简洁、优雅、易读,提高代码的可维护性。本文通过一个例子介绍了如何定义和使用自定义注解。在实际开发中,我们可以结合 AOP、反射等技术,使用自定义注解来实现更多的功能。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6月前
|
存储 C++
【C++】可变参数模板使用总结(简洁易懂,详细,含代码演示)
【C++】可变参数模板使用总结(简洁易懂,详细,含代码演示)
|
1月前
|
并行计算 Java API
探索Java中的Lambda表达式:简化代码,提高可读性
【10月更文挑战第5天】Lambda表达式在Java 8中引入,旨在简化集合操作和并行计算。本文通过介绍Lambda表达式的基本概念、语法结构以及实际应用示例,展示了如何利用这一特性编写更加简洁、易读的代码。我们将从Lambda的基础入手,逐步深入到其在函数式接口中的应用,并探讨其对Java编程范式的影响。
|
3月前
|
算法 Java API
探索Java中的Lambda表达式:简化代码,提升可读性
Lambda表达式,这一现代编程语言的闪亮特性,在Java 8中首次亮相,为开发者提供了一种更加紧凑、易读的编写匿名函数的方式。本文将深入解析Lambda表达式如何优化我们的代码结构,提高开发效率,并探讨其在多线程编程中的应用。我们将通过具体示例,展示Lambda表达式的魅力,帮助读者更好地理解和运用这一强大的工具。
49 2
|
6月前
|
开发者
在实际项目中,如何使用装饰器来提高代码的可读性和可维护性?
【2月更文挑战第18天】【2月更文挑战第54篇】在实际项目中,如何使用装饰器来提高代码的可读性和可维护性?
34 0
|
6月前
|
安全 Java 编译器
Java注解详解和自定义注解实战,用代码讲解
Java注解详解和自定义注解实战,用代码讲解
176 0
|
XML 缓存 Java
Java注解怎么用
Java注解怎么用
227 0
|
前端开发 JavaScript Java
Java注解详解以及如何实现自定义注解
Java注解详解以及如何实现自定义注解
312 1
|
SQL XML Java
MyBatis框架:第七章:注解使用方式和参数传递及#{}和${}
MyBatis框架:第七章:注解使用方式和参数传递及#{}和${}
331 0
|
Java 编译器 API
Java注解—高级用法与深入解读(2)
Java注解—高级用法与深入解读(2)
201 0
Java注解—高级用法与深入解读(2)
|
Java 编译器 数据库
Java注解—高级用法与深入解读(1)
Java注解—高级用法与深入解读(1)
387 0
Java注解—高级用法与深入解读(1)