package com.example.scaffold.learning; import com.example.scaffold.learning.reflection.ReflectionLabTarget; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/learning/reflection") public class ReflectionLearningController { @GetMapping("/overview") public Map overview() { return Map.of( "whatIsReflection", List.of( "运行时检查类、字段、方法、构造器", "运行时动态创建对象", "运行时调用方法、读写字段", "Spring / MyBatis / Jackson 等框架大量依赖反射" ), "whyItMatters", List.of( "理解框架为什么能自动装配、自动绑定、自动序列化", "理解代理、注解扫描、Bean 创建背后的机制", "理解反射带来的灵活性与性能成本" ) ); } @GetMapping("/class-info") public Map classInfo() throws Exception { Class clazz = ReflectionLabTarget.class; Map result = new LinkedHashMap<>(); result.put("className", clazz.getName()); result.put("simpleName", clazz.getSimpleName()); result.put("constructors", Arrays.stream(clazz.getDeclaredConstructors()).map(Constructor::toString).toList()); result.put("fields", Arrays.stream(clazz.getDeclaredFields()).map(Field::toString).toList()); result.put("methods", Arrays.stream(clazz.getDeclaredMethods()).map(Method::toString).toList()); return result; } @GetMapping("/instantiate") public Map instantiate(@RequestParam(defaultValue = "ref-user") String name, @RequestParam(defaultValue = "5") int count) throws Exception { Constructor constructor = ReflectionLabTarget.class.getDeclaredConstructor(String.class, int.class); ReflectionLabTarget obj = constructor.newInstance(name, count); return Map.of( "instance", obj.getClass().getName(), "identityHashCode", System.identityHashCode(obj), "name", obj.getName(), "count", obj.getCount(), "message", "通过反射构造器动态创建对象成功" ); } @GetMapping("/field-access") public Map fieldAccess(@RequestParam(defaultValue = "changed-by-reflection") String value) throws Exception { ReflectionLabTarget obj = new ReflectionLabTarget(); Field field = ReflectionLabTarget.class.getDeclaredField("name"); field.setAccessible(true); Object before = field.get(obj); field.set(obj, value); Object after = field.get(obj); return Map.of( "field", field.getName(), "before", before, "after", after, "message", "私有字段已通过反射修改" ); } @GetMapping("/method-call") public Map methodCall(@RequestParam(defaultValue = "你好") String prefix) throws Exception { ReflectionLabTarget obj = new ReflectionLabTarget("Spring", 2); Method publicMethod = ReflectionLabTarget.class.getDeclaredMethod("greet", String.class); Object publicResult = publicMethod.invoke(obj, prefix); Method privateMethod = ReflectionLabTarget.class.getDeclaredMethod("secretFormula", String.class); privateMethod.setAccessible(true); Object privateResult = privateMethod.invoke(obj, "debug"); Method staticMethod = ReflectionLabTarget.class.getDeclaredMethod("staticInfo"); Object staticResult = staticMethod.invoke(null); return Map.of( "publicMethodResult", publicResult, "privateMethodResult", privateResult, "staticMethodResult", staticResult, "message", "公开方法、私有方法、静态方法都已通过反射调用" ); } @GetMapping("/why-frameworks-use-it") public Map whyFrameworksUseIt() { return Map.of( "spring", List.of("扫描注解", "创建 Bean", "依赖注入", "调用生命周期方法"), "jackson", List.of("读取字段", "调用 getter/setter", "对象序列化/反序列化"), "mybatis", List.of("结果集映射到对象", "动态代理 Mapper 接口"), "warning", "反射很强大,但要理解它的性能成本、可读性成本和封装破坏风险" ); } }