注解学习:一个实体类添加get和set功能的注解

1、注解

首先我们需要写一个注解:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AddGetterSetter {
}

该注解有两个元注解,其中 @Retention(RetentionPolicy.RUNTIME) 指定了该注解在运行时保留,@Target(ElementType.TYPE) 指定该注解只能用于类上。

2、注解处理器

接下来,我们需要一个注解处理器来处理这个注解并自动生成 getter 和 setter 方法

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class AddGetterSetterProcessor {

    public static void process(Class<?> clazz) {
        if (!clazz.isAnnotationPresent(AddGetterSetter.class)) {
            return;
        }

        for (Field field : clazz.getDeclaredFields()) {
            String fieldName = field.getName();
            String capitalizedFieldName = capitalize(fieldName);

            try {
                clazz.getMethod("get" + capitalizedFieldName);
            } catch (NoSuchMethodException e) {
                addGetter(clazz, fieldName);
            }

            try {
                clazz.getMethod("set" + capitalizedFieldName, field.getType());
            } catch (NoSuchMethodException e) {
                addSetter(clazz, fieldName, field.getType());
            }
        }
    }

    private static String capitalize(String s) {
        if (s == null || s.isEmpty()) {
            return s;
        }
        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }

    private static void addGetter(Class<?> clazz, String fieldName) {
        String capitalizedFieldName = capitalize(fieldName);
        String getterName = "get" + capitalizedFieldName;
        String getterBody = "return " + fieldName + ";";

        String getterCode = "public " + clazz.getSimpleName() + " " + getterName + "() { " + getterBody + " }";

        try {
            clazz.getDeclaredMethod(getterName);
        } catch (NoSuchMethodException e) {
            try {
                clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e1) {
                throw new RuntimeException(e1);
            }

            try {
                clazz.getDeclaredMethod(getterName);
            } catch (NoSuchMethodException e2) {
                addMethod(clazz, getterCode);
            }
        }
    }

    private static void addSetter(Class<?> clazz, String fieldName, Class<?> fieldType) {
        String capitalizedFieldName = capitalize(fieldName);
        String setterName = "set" + capitalizedFieldName;
        String setterBody = "this." + fieldName + " = " + fieldName + ";";

        String setterCode = "public void " + setterName + "(" + fieldType.getSimpleName() + " " + fieldName + ") { " + setterBody + " }";

        try {
            clazz.getDeclaredMethod(setterName, fieldType);
        } catch (NoSuchMethodException e) {
            try {
                clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e1) {
                throw new RuntimeException(e1);
            }

            try {
                clazz.getDeclaredMethod(setterName, fieldType);
            } catch (NoSuchMethodException e2) {
                addMethod(clazz, setterCode);
            }
        }
    }

    private static void addMethod(Class<?> clazz, String code) {
        try {
            Class<?> compiler = Class.forName("javax.tools.ToolProvider");
            Object javac = compiler.getMethod("getSystemJavaCompiler").invoke(null);

            Class<?> fileManagerClass = Class.forName("com.sun.tools.javac.api.JavacFileManager");

3、使用

注解有了,注解处理器也有了,那怎么让注解生效呢?
在 Spring Boot 中,注解处理器也是通过注解来定义的。你需要定义一个被 @Component 或者 @Service 等注解修饰的类,然后实现 org.springframework.beans.factory.config.BeanDefinitionRegistryPostProcessor 接口。该接口是 Spring 的扩展点接口,可以在 Spring 应用启动时,动态注册 Bean 定义。

接下来,你需要在应用程序的配置类上,使用 @Import 注解引入你定义的注解处理器类。这样,Spring Boot 在启动时会扫描你的注解处理器类,并自动调用其中的方法。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class AddGetterSetterRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AddGetterSetterProcessor.class);
        BeanDefinition beanDefinition = builder.getBeanDefinition();
        registry.registerBeanDefinition("addGetterSetterProcessor", beanDefinition);
    }
}

在你的应用程序的配置类上,使用 @Import 注解引入这个类即可:

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(AddGetterSetterRegistrar.class)
public class AppConfig {
    //...
}

这样,当你的应用程序启动时,Spring Boot 会自动扫描 AddGetterSetterProcessor 类,并调用其 process 方法来处理使用了 AddGetterSetter 注解的类,为其自动生成 getter 和 setter 方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值