zl程序教程

您现在的位置是:首页 >  其他

当前栏目

注解带来的好处,注解如何简化代码

2023-03-31 10:45:22 时间

什么是注解

我学习注解还不理解注解的作用在哪里。Spring 中大量使用注解,Servlet 也使用注解,总之很多地方都使用注解,但凡用到注解的地方都能很明显地感觉到可以少写很多配置文件和代码。注释不被程序编译,注释是给人看的;注解会被程序编译,是给程序看的,字段、类通过反射可以拿到注解中的信息。

体验注解的作用

写一个简单的注解,注解的写法和接口相似,这里就不讨论注解的本质、注解的元注解。只需要知道元注解就是让注解在“什么时候用”和“哪里用”。

1️⃣ 写一个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Property {
  String name();
  String value();
}

2️⃣ 在类属性上使用注解:

public class User {
  @Property(name = "username", value = "Hello World!")
  private String username;
  @Property(name = "password", value = "123123")
  private String password;
}

3️⃣ 获取类属性上的注解:

public static void main(String[] args) {
  Class<User> user = User.class;
  for (Field field : user.getDeclaredFields()) {
    Property annotation = field.getAnnotation(Property.class);
    System.out.println(annotation.name() + "=>" + annotation.value());
  }
}

通过反射,可以获取类中的注解、字段、函数等。第一,我们要获取类中的所有字段(属性),循环遍历出每一个字段;第二,通过字段获取注解;第三,调用注解中提供的抽象函数。

image

注解简化配置文件

配置数据库一般写在.properties.yml.xml,通过输入流或者其他读取配置文件信息,把我们所需要的数据注入到类、函数使用。有了注解,就完全可以不需要写这些配置文件。

写注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DataConfigure {
  String url();
  String username();
  String password();
}

写配置类

@Data
public class Config {
  private String username;
  private String password;
  private String url;
}

这个类上我写了一个@Data注解,这是 lombok 提供的,用于简化 getter 和 setter 这种胶水代码。

@DataConfigure(url = "jdbc:mysql://localhost:3306/db", username = "root", password = "123123")
public class MySQLConfig extends Config {
}

获取数据

public class LoadConfig<T extends Config> {
  private final T config;

  public LoadConfig(Class<T> clz) {
    try {
      config = clz.getDeclaredConstructor().newInstance();
      DataConfigure annotation = clz.getAnnotation(DataConfigure.class);
      config.setPassword(annotation.password());
      config.setUsername(annotation.username());
      config.setUrl(annotation.url());
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
      throw new RuntimeException(e);
    }
  }

}

测试配置类

传递一个 Config 的子类,只需要修改配置类就能实现切换数据库。决定权交给调用者,而不是被调用者。

public class Main {
  public static void main(String[] args) {
    LoadConfig<MySQLConfig> mysql = new LoadConfig<>(MySQLConfig.class);
    LoadConfig<SqlServerConfig> sqlServer = new LoadConfig<>(SqlServerConfig.class);
    System.out.println(mysql.getConfig().toString());
    System.out.println(sqlServer.getConfig().toString());
  }
}

image