java 注解

Java 注解(Annotation)是 Java 5 引入的一种元数据形式,允许开发者在代码中嵌入信息,这些信息可以在编译时、类加载时或运行时被读取和处理。注解不会直接影响代码的逻辑,但可以通过框架和工具提供额外的信息和功能。以下是关于 Java 注解的详细介绍:

1. 注解的定义

注解使用 @ 符号来定义,可以用于类、方法、字段、参数等。例如:

public @interface MyAnnotation {
    String value();
}

2. 常见的内置注解

Java 提供了一些常用的内置注解,包括:

  • @Override:用于表示一个方法重写了超类的方法。
  • @Deprecated:表示一个方法、类或字段不推荐使用。
  • @SuppressWarnings:用于抑制特定类型的编译器警告。

3. 元注解

元注解是注解的注解,用于定义其他注解的特性。常见的元注解有:

  • @Retention:指定注解的生命周期(SOURCE、CLASS、RUNTIME)。
  • @Target:指定注解可以应用的 Java 元素类型(类、方法、字段等)。
  • @Documented:表示使用该注解的元素将包含在 Javadoc 中。
  • @Inherited:表示该注解可以被子类继承。

4. 使用注解

可以通过反射机制在运行时访问注解信息。例如:

@MyAnnotation("example")
public class MyClass {
    @MyAnnotation("method")
    public void myMethod() {}
}

// 访问注解
MyAnnotation annotation = MyClass.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value());

注解是用来给程序看的注释,当程序解析到这个注解时,会进行你指定的操作。反射机制才是其灵魂,有反射机制,注解才有用。 通过注解来控制程序的执行行为。

5.使用示例

构建自定义注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
    String value();  // 描述测试的目的
    int count() default 1;  // 运行测试的次数,默认为1
}

构建需要注解的类

public class CalculatorTests {

    @Test(value = "Test addition", count = 3)
    public void testAddition() {
        int result = 2 + 3;
        System.out.println("Addition Test Result: " + result); // 结果应为5
    }

    @Test(value = "Test subtraction", count = 2)
    public void testSubtraction() {
        int result = 5 - 2;
        System.out.println("Subtraction Test Result: " + result); // 结果应为3
    }
}

注解的真正使用

import java.lang.reflect.Method;

public class TestRunner {
    public static void main(String[] args) {
        Class<CalculatorTests> testClass = CalculatorTests.class;

        // 获取所有方法
        for (Method method : testClass.getDeclaredMethods()) {
            // 检查方法是否有 @Test 注解
            if (method.isAnnotationPresent(Test.class)) {
                Test testAnnotation = method.getAnnotation(Test.class);
                String description = testAnnotation.value();
                int count = testAnnotation.count();

                // 执行测试方法指定的次数
                for (int i = 0; i < count; i++) {
                    System.out.println("Running: " + description + " (Run " + (i + 1) + ")");
                    try {
                        method.invoke(new CalculatorTests()); // 调用测试方法
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

invoke()函数,invoke 是 Java 反射 API 中 Method 类的一个方法,用于调用类中的某个方法。

Object invoke(Object obj, Object... args) throws IllegalAccessException, InvocationTargetException;
  • obj:这是要调用方法的对象实例。如果方法是静态的,这里可以传递 null

  • args:这是一个可变参数,表示传递给方法的参数。如果方法没有参数,可以传递空数组或不传递此参数。

invoke 方法返回调用结果,返回类型为 Object,如果方法返回 void,则返回 null

import java.lang.reflect.Method;

public class Example {
    public void sayHello(String name) {
        System.out.println("Hello, " + name + "!");
    }

    public static void main(String[] args) {
        try {
            // 创建 Example 类的实例
            Example example = new Example();

            // 获取 sayHello 方法
            Method method = Example.class.getMethod("sayHello", String.class);

            // 使用 invoke 调用 sayHello 方法
            method.invoke(example, "Alice"); // 输出: Hello, Alice!
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在springboot中 注解很多是和aop结合使用,当然也可以不使用,这里给一个不使用aop的例子

//定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecution {
    String value() default "Executing method"; // 可选的描述信息
}


//使用注解
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @LogExecution("Performing action")
    public void performAction() {
        // 手动检查注解并执行相应逻辑
        LogExecution logExecution = this.getClass().getMethod("performAction").getAnnotation(LogExecution.class);
        
        if (logExecution != null) {
            System.out.println(logExecution.value() + " - Method started");
        }

        // 业务逻辑
        System.out.println("Action is being performed...");
    }
}


//控制器调用
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    private final MyService myService;

    public MyController(MyService myService) {
        this.myService = myService;
    }

    @GetMapping("/perform")
    public String perform() {
        myService.performAction();
        return "Action performed!";
    }
}


//启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}


//结果
Performing action - Method started
Action is being performed...

但是,这中把注解的使用逻辑写进service中和不使用注解直接在service其中写对应的逻辑是没有什么区别的(甚至使用注解更繁琐),简直是多此一举,所以 一般情况下还是和aop 进行结合使用。

@Aspect
@Component
public class LoggingAspect {
    @Around("@annotation(LogExecution)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        // AOP 逻辑
        System.out.println("Method is being executed...");
        return joinPoint.proceed(); // 调用原方法
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值