java——反射与注解(下)

简介: java——反射与注解

Java注解进阶


深入学习Java注解的应用场景,例如框架设计、代码生成、单元测试等;掌握各种内置注解和第三方注解库的使用方法,提高注解编程的效率和可维护性。

Java注解是一种元数据,在Java语言中广泛应用于框架设计、代码生成、单元测试等场景。Java提供了很多内置注解,同时也有很多第三方注解库可以使用。


下面介绍Java注解的进阶应用场景,以及各种内置注解和第三方注解库的使用方法。


1. 应用场景


1)框架设计:Java注解可以用来标记业务逻辑、数据访问对象、服务等,以便框架能够自动生成代码或配置文件。


2)代码生成:Java注解可以用来标记需要生成的类、方法、字段等信息,并根据注解生成对应的代码。


3)单元测试:Java注解可以用来标记测试方法和测试类,以便测试框架能够自动运行测试。


4)持久化:Java注解可以用来标记实体类和数据库表之间的映射关系,以便ORM框架能够自动处理持久化操作。


2. 内置注解


Java提供了很多内置注解,常用的有以下几种:


1)@Override:表示方法覆盖父类的方法。


2)@Deprecated:表示方法已经过时,建议不再使用。


3)@SuppressWarnings:表示抑制编译器警告。


4)@SafeVarargs:表示有参数数量可变的方法或构造函数是类型安全的。


5)@FunctionalInterface:表示接口是一个函数式接口。


示例代码:

public class MyClass {
    @Override
    public String toString() {
        return "MyClass";
    }
    @Deprecated
    public void oldMethod() { }
    @SuppressWarnings("unchecked")
    public void test() {
        List list = new ArrayList();
        list.add("Hello");
    }
    @SafeVarargs
    public final <T> void print(T... args) {
        for (T arg : args) {
            System.out.print(arg);
        }
    }
    @FunctionalInterface
    interface MyInterface {
        void doSomething();
    }
}


3. 第三方注解库


除了内置注解,Java还有很多第三方注解库可以使用,常用的有以下几种:


1)Lombok:可以自动生成getter、setter、toString、equals、hashCode等方法的注解库。


2)Jackson:可以实现JSON序列化和反序列化的注解库。


3)Hibernate Validator:可以实现数据校验的注解库。


4)Swagger:可以生成API文档的注解库。


示例代码:

@Data
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}
public class JacksonTest {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        User user = new User("Alice", 18);
        String json = mapper.writeValueAsString(user);
        System.out.println(json); // {"name":"Alice","age":18}
        User user2 = mapper.readValue(json, User.class);
        System.out.println(user2.getName()); // Alice
    }
}
public class ValidatorTest {
    @NotNull
    @Size(min = 3, max = 20)
    private String name;
    @Min(18)
    private int age;
    public ValidatorTest(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static void main(String[] args) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        ValidatorTest test = new ValidatorTest("Alice", 16);
        Set<ConstraintViolation<ValidatorTest>> violations = validator.validate(test);
        for (ConstraintViolation<ValidatorTest> violation : violations) {
            System.out.println(violation.getMessage()); // must be greater than or equal to 18
        }
    }
}
@RestController
public class UserController {
    @GetMapping("/users")
    @ApiOperation(value = "Get all users")
    public List<User> getUsers() { ... }
    @PostMapping("/users")
    @ApiOperation(value = "Create a user")
    public void createUser(@Valid @RequestBody User user) { ... }
}


以上是Java注解的进阶应用场景、各种内置注解和第三方注解库的使用方法。希望可以帮助您更好地理解和应用Java注解。


4. 总结


Java注解是一种元数据,在Java语言中广泛应用于框架设计、代码生成、单元测试等场景。Java提供了很多内置注解,同时也有很多第三方注解库可以使用。通过学习Java注解,我们可以提高注解编程的效率和可维护性。


示例代码:

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String value();
}
public class MyClass {
    @MyAnnotation("Hello")
    public void sayHello() { }
}
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        MyClass obj = new MyClass();
        Method method = obj.getClass().getMethod("sayHello");
        MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
        if (annotation != null) {
            System.out.println(annotation.value()); // Hello
        }
    }
}


Java反射与注解实战


在实际项目中应用Java反射和注解技术,例如使用反射实现IOC容器或AOP功能,使用注解进行数据校验或权限控制等。

Java反射和注解是Java编程中非常重要的概念,可以通过反射获取类、方法、字段等信息,并且可以使用注解来标记业务逻辑、数据访问对象、服务等。下面给出一个Java反射和注解的实战代码详解。


1. 实战场景


假设我们正在开发一个简单的社交应用,需要根据用户输入的API路径动态调用对应的服务方法,并返回结果。例如,当用户输入/api/user/get时,我们需要调用UserService中的get()方法,当用户输入/api/post/add时,我们需要调用PostService中的add()方法。


2. 代码实现


首先,我们定义一个@Service注解,用于标记服务类和服务方法:

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Service {
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Action {
    String value();
}


然后,我们定义两个服务类UserService和PostService,并在类上添加@Service注解,表示这是一个服务类:

@Service("user")
public class UserService {
    public void get() {
        System.out.println("Get user...");
    }
}
@Service("post")
public class PostService {
    public void add() {
        System.out.println("Add post...");
    }
}


接下来,我们实现一个API调度器DispatcherServlet,它根据用户输入的API路径,调用对应的服务方法:

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class DispatcherServlet {
    private Map<String, Object> beans = new HashMap<>();
    public void init() throws Exception {
        // 扫描服务类,并创建实例
        ClassPathScanUtil scanner = new ClassPathScanUtil("com.example.service");
        for (String className : scanner.getFullyQualifiedClassNameList()) {
            Class<?> clazz = Class.forName(className);
            if (clazz.isAnnotationPresent(Service.class)) {
                Service service = clazz.getAnnotation(Service.class);
                String serviceName = service.value();
                Object instance = clazz.newInstance();
                beans.put(serviceName, instance);
            }
        }
        // 注册服务方法
        for (Object instance : beans.values()) {
            Class<?> clazz = instance.getClass();
            if (clazz.isAnnotationPresent(Service.class)) {
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(Action.class)) {
                        Action action = method.getAnnotation(Action.class);
                        String actionName = action.value();
                        String serviceName = clazz.getAnnotation(Service.class).value();
                        String key = "/" + serviceName + "/" + actionName;
                        ActionHandler handler = new ActionHandler(instance, method);
                        HandlerMapping.register(key, handler);
                    }
                }
            }
        }
    }
    public void dispatch(String apiPath) throws Exception {
        // 调用服务方法
        ActionHandler handler = HandlerMapping.get(apiPath);
        if (handler != null) {
            handler.invoke();
        } else {
            System.out.println("API path not found.");
        }
    }
}


在DispatcherServlet中,我们首先扫描服务类,并创建实例;然后,遍历每个服务类的方法,如果有@Action注解,则将其注册到HandlerMapping中;最后,根据用户输入的API路径,调用对应的服务方法。


HandlerMapping是一个静态类,它保存了API路径和对应的ActionHandler。ActionHandler封装了服务类实例和服务方法,可以通过invoke()方法来调用服务方法。

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class HandlerMapping {
    private static Map<String, ActionHandler> mappings = new HashMap<>();
    public static void register(String key, ActionHandler handler) {
        mappings.put(key, handler);
    }
    public static ActionHandler get(String key) {
        return mappings.get(key);
    }
}
public class ActionHandler {
    private Object instance;
    private Method method;
    public ActionHandler(Object instance, Method method) {
        this.instance = instance;
        this.method = method;
    }
    public void invoke() throws Exception {
        method.invoke(instance);
    }
}


最后,我们在main()方法中使用DispatcherServlet来处理API请求:

public class Main {
    public static void main(String[] args) throws Exception{
        DispatcherServlet servlet = new DispatcherServlet();
        servlet.init();
        servlet.dispatch("/user/get");
        servlet.dispatch("/post/add");
        servlet.dispatch("/comment/list");
    }
}


在这个例子中,我们使用Java反射和注解实现了一个简单的API调度器。通过@Service注解,我们标记了服务类;通过@Action注解,我们标记了服务方法。通过DispatcherServlet,我们扫描服务类并创建实例,然后注册服务方法到HandlerMapping中。最后,在处理API请求时,我们根据API路径获取对应的ActionHandler,并通过反射调用服务方法。

相关文章
|
29天前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
86 43
Java学习十六—掌握注解:让编程更简单
|
23天前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
44 14
|
23天前
|
前端开发 Java
[Java]讲解@CallerSensitive注解
本文介绍了 `@CallerSensitive` 注解及其作用,通过 `Reflection.getCallerClass()` 方法返回调用方的 Class 对象。文章还详细解释了如何通过配置 VM Options 使自定义类被启动类加载器加载,以识别该注解。涉及的 VM Options 包括 `-Xbootclasspath`、`-Xbootclasspath/a` 和 `-Xbootclasspath/p`。最后,推荐了几篇关于 ClassLoader 的详细文章,供读者进一步学习。
29 12
|
26天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
17 0
[Java]反射
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
65 9
Java——反射&枚举
|
1月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
|
17天前
|
Java 编译器
Java进阶之标准注解
Java进阶之标准注解
28 0
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
1月前
|
JSON Java 数据库
java 常用注解大全、注解笔记
关于Java常用注解的大全和笔记,涵盖了实体类、JSON处理、HTTP请求映射等多个方面的注解使用。
35 0
java 常用注解大全、注解笔记
|
1月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0