java反射案例

一、简单注解案例

1.1 编写注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}

1.2 注入注解

public class Testable {
public void execute() {
System.out.println("executing...");
}

@Test
void testExecute() {
execute();
}
}

1.3 编写注解处理器

public class TestTracker {
public static void invoke(String[] classes) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if (!(classes.length > 0)) {
System.out.println("classes为空!");
System.exit(0);
}
for (String className : classes) {
Class<?> clazz = Class.forName(className);
if (clazz == null) {
continue;
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Annotation[] anns = method.getDeclaredAnnotations();
if (anns.length < 1) {
continue;
}
for (Annotation ann : anns) {
if (ann instanceof Test) {
Constructor<?> constructor = clazz.getConstructor();
Testable o = (Testable)constructor.newInstance();
method.setAccessible(true);
System.out.println(method.getName());
method.invoke(o);
}
}
}
}
}
}

1.4 运行测试

public class Main {
public static void main(String[] args) {
testTestTracker();
}

static void testTestTracker(){
String[] tests = new String[]{"com.bamboo.demo.Testable"};
try {
TestTracker.invoke(tests);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

1.5 测试结果

testExecute
executing...

二、SQL注解案例

2.1 编写注解

2.1.1 Constraints注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
boolean primaryKey() default false;

boolean allowNull() default true;

boolean unique() default false;
}

2.1.2 SQLInteger注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
String name() default "";
Constraints constraints() default @Constraints;
}

2.1.3 SQLString注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
int value() default 0;
String name() default "";
Constraints constraints() default @Constraints;
}

2.1.4 Uniquenss注解

public @interface Uniquenss {
Constraints constraints() default @Constraints(unique = true);
}

2.2 注入注解

@DBTable(name = "MEMBER")
public class Member {
@SQLString(30)
private String firstName;
@SQLString(50)
private String lastName;
@SQLInteger
private Integer age;
@SQLString(value = 30,constraints = @Constraints(primaryKey = true))
private String handle;
static int memberCount;
public String getFirstName() {
return firstName;
}

public String getLastName() {
return lastName;
}

public Integer getAge() {
return age;
}

public String getHandle() {
return handle;
}

@Override
public String toString() {
return handle;
}
}

2.3 编写注解处理器

public class TableCreator {
public static String create(String[] classes) throws ClassNotFoundException {
if (classes.length < 1) {
System.out.println("classes: annotated classes");
System.exit(0);
}
// 遍历每一个table表单Class
for (String className : classes) {
// 获取表单的反射类
Class<?> cl = Class.forName(className);
// 获取表单名注解
DBTable dbTable = cl.getDeclaredAnnotation(DBTable.class);
// 没有获取到说明这个类不是表单,进入下一次循环
if (dbTable == null) {
System.out.println("No DBTable annotations in class " + className);
continue;
}
// 获取表单注解的名字为表名
String tableName = dbTable.name();
if (tableName.isEmpty()) {
tableName = cl.getName().toUpperCase();
}
// 创建一个集合来存储列代码
List<String> columnDefs = new ArrayList<>();
// 通过获取反射类所有的域来进行查找域变量注解
for (Field field : cl.getDeclaredFields()) {
// 这是一个通用的列名,获取的列名都保存在这里
@SuppressWarnings("all")
String columnName = null;
// 获取所有域的注解
Annotation[] anns = field.getDeclaredAnnotations();
// 当域注解长度不足 1 时,说明这个域没有标识注解,进行下一个域判断
if (anns.length < 1) {
continue; // not a db table column
}
// 遍历每个注解直至找到SQL相关注解
for (Annotation ann : anns) {
// SQLInteger判断
if (ann instanceof SQLInteger) {
SQLInteger sInt = (SQLInteger) anns[0];
// use field name if name not specified
if (sInt.name().isEmpty()) {
columnName = field.getName().toUpperCase();
} else {
columnName = sInt.name();
}
columnDefs.add(columnName + " INT" +
getConstraints(sInt.constraints())
);
break;
}
// SQLString判断
if (ann instanceof SQLString) {
SQLString sString = (SQLString) anns[0];
// use field name if name not specified
if (sString.name().isEmpty()) {
columnName = field.getName().toUpperCase();
} else {
columnName = sString.name();
}
columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" +
getConstraints(sString.constraints())
);
break;
}
}
}
StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "(");
for (String columnDef : columnDefs) {
createCommand.append("\n " + columnDef + ",");
}
// remove trailing comma
String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");";
return tableCreate;
}
return null;
}

private static String getConstraints(Constraints con) {
StringBuilder constraints = new StringBuilder();
if (!con.allowNull()) {
constraints.append(" NOT NULL");
}
if (con.primaryKey()) {
constraints.append(" PRIMARY KEY");
}
if (con.unique()) {
constraints.append(" UNIQUE");
}
return constraints.toString();
}
}

2.4 运行测试

public class Main {
public static void main(String[] args) {
testCreateTable();
}

static void testCreateTable() {
try {
String code = TableCreator.create(new String[]{"com.bamboo.demo.Member"});
System.out.println(code);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

2.5 测试结果

CREATE TABLE MEMBER(
FIRSTNAME VARCHAR(30),
LASTNAME VARCHAR(50),
AGE INT,
HANDLE VARCHAR(30) PRIMARY KEY);