在框架的基本原理上篇中,笔者介绍了框架的灵魂:反射机制。使用反射机制,在不改动代码的前提下,只需要改动配置文件中的类名、方法名,就可以创建任意类的对象,可以执行任意方法,这就是框架内部的基本原理。本篇将介绍如何使用注解,将上篇中的配置文件省略并简化代码,达到相同的功能。
首先,我们新建一个Person类,内容与上篇中相同;新建一个注解接口;新建一个测试类。
Person类中的代码为:
package top.imcyc.day07.annotation;
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat() {
System.out.println("eat......");
}
}
注解接口中的代码为:
package top.imcyc.day07.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
String className();
String methodName();
}
测试类中的代码为:
package top.imcyc.day07.annotation;
import java.lang.reflect.Method;
@Pro(className = "top.imcyc.day07.annotation.Person", methodName = "eat")
public class reflectTest {
public static void main(String[] args) throws Exception {
//解析注解(获取注解的属性值)
// 1. 获取该类的字节码文件对象
Class<reflectTest> reflectTestClass = reflectTest.class;
// 2. 获取顶部的注解的对象
// 其实就是在内存中生成了一个该注解接囗的子类实现对象,子类重写了className和methodName方法,返回的就是"...Person"和"eat"字符串
Pro an = reflectTestClass.getAnnotation(Pro.class);
//最终目的是拿到顶部注解里定义的属性值
String s = an.className();
String s1 = an.methodName();
Class cls = Class.forName(s);//获取s代表的类的字节码文件对象
Object obj = cls.newInstance();//获取一个类对象
Method method = cls.getMethod(s1);//获取该类的方法
method.invoke(obj);//执行此方法,参数传入要被执行的方法对应的类对象
}
}
可以看到,测试类顶部注解里的属性值就代替了原来配置文件里的内容,省去了设置配置文件,简化了测试代码,同时保持了程序的扩展性。满足在不改动代码的前提下,只需要改动顶部注解的属性值,就可以创建任意类的对象,可以执行任意方法。
下篇入口。