一、反射基础方法
1. 获取 Class 对象
Class<?> clazz1 = Class.forName("com.example.User");//灵活
Class<?> clazz2 = User.class;//编译期就确定类型,最快最高效
Class<?> clazz3 = new User().getClass();//需要实例化对象
2. 创建对象
Object obj = clazz.getDeclaredConstructor().newInstance();//编译期不知道类型,运行期动态创建
3. 获取方法
Method[] methods = clazz.getMethods();//返回所有公共成员方法数组,包括继承
Method[] methods = clazz.getDeclaredMethods();//返回所有成员方法数组,不包括继承
Method method = clazz.getMethod("getUserInfo");//返回单个公共成员方法
Method method = clazz.getDeclaredMethod("getUserInfo");//返回单个成员方法
4. 获取注解
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping mapping = method.getAnnotation(RequestMapping.class);
String path = mapping.value();//读取路由路径
}
5. 动态执行方法
method.invoke(obj);//方法是谁、在哪个类、什么时候执行 —— 全部运行时决定
二、项目结构设计
com.jincheng.fensheDemo
├── annotation
│ ├── RestController.java
│ └── RequestMapping.java
├── controller
│ └── UserController.java
├── core
│ └── DispatcherServlet.java
└── Application.java
三、定义注解
1. @RestController
@Target(ElementType.TYPE)//这个注解只能贴在类、接口、枚举上,不能贴在方法或字段上。
@Retention(RetentionPolicy.RUNTIME)//这个注解在运行时保留,反射可以读到它。
public @interface RestController {
}
标记:这是一个控制器
2. @RequestMapping
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value();// 存储路由路径
}
标记:方法对应的 URL
四、编写 Controller
@RestController
public class UserController {
@RequestMapping("/api/user/info")// 假设这是一个处理 GET 请求的方法
public String getUserInfo() {
return "{\"name\": \"Developer\", \"role\": \"Admin\"}";
}
@RequestMapping("/api/system/status")
public String getStatus() {
return "{\"status\": \"System Running Normal\"}";
}
}
五、反射核心:DispatcherServlet
1. 核心数据结构
private Map<String, Method> handlerMapping = new HashMap<>();//路由表 路径->对应的方法(method对象)
private Map<Class<?>, Object> controllerMap = new HashMap<>();简易 IoC 容器 Controller的Class -> 对应的实例对象
2. 初始化(扫描 + 注册)
/**
* 初始化框架:传入需要被扫描的类
*/
public void init(Class<?>... classes) throws Exception {
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(RestController.class)) {
// 动态创建实例
Object instance = clazz.getDeclaredConstructor().newInstance();
controllerMap.put(clazz, instance);
// 扫描方法
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping mapping = method.getAnnotation(RequestMapping.class);
String path = mapping.value();
handlerMapping.put(path, method);
System.out.println("[Router Init] Mapped URL: " + path + " -> " + clazz.getSimpleName() + "." + method.getName());
}
}
}
}
}
3. 请求分发(动态调用)
/**
* 模拟处理 HTTP 请求
*/
public Object dispatch(String path) throws Exception {
// 查路由表,找对应方法
Method method = handlerMapping.get(path);
if (method != null) {
// 找到该方法属于哪个类
Class<?> clazz = method.getDeclaringClass();
//ioc
Object instance = controllerMap.get(clazz);
//动态执行方法 (invoke)
return method.invoke(instance);
}
return "404 Not Found";
}
六、启动测试
public static void main(String[] args) {
DispatcherServlet dispatcher = new DispatcherServlet();
dispatcher.init(UserController.class);
System.out.println(dispatcher.dispatch("/api/user/info"));
System.out.println(dispatcher.dispatch("/api/system/status"));
System.out.println(dispatcher.dispatch("/api/unknown"));
}
if ("/api/user/info".equals(path)) {
return new UserController().getUserInfo();
}//强耦合 ,不可扩展