Java 反射机制深度笔记
一、反射基础:Class 类
1. Class 对象的获取方式
| 获取方式 | 代码示例 | 适用场景 | 
|---|
| 类名.class | Class<User> clazz = User.class; | 编译时已知类名 | 
| 对象.getClass() | user.getClass(); | 已有对象实例 | 
| Class.forName() | Class.forName("com.example.User"); | 动态加载类 | 
| 类加载器 | ClassLoader.loadClass("com.example.User"); | 自定义类加载 | 
2. Class 类核心方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  Constructor<?>[] getConstructors();   Constructor<T> getConstructor(Class<?>... parameterTypes);
 
  Field getField(String name);          Field getDeclaredField(String name); 
 
  Method getMethod(String name, Class<?>... parameterTypes); Method getDeclaredMethod(String name, Class<?>... parameterTypes);
 
  T newInstance();                      Constructor.newInstance(Object... initargs); 
 
  | 
3. 类型检查方法
1 2 3 4 5
   | isInterface()       isArray()           isEnum()            isPrimitive()       isAnnotationPresent(Class<? extends Annotation> annotationClass) 
 
  | 
二、反射操作实践
1. 字段操作示例
1 2 3 4 5 6 7 8 9 10 11 12 13
   | public class ReflectFieldDemo {     public static void main(String[] args) throws Exception {         User user = new User("张三", 25);         Class<?> clazz = user.getClass();                           Field ageField = clazz.getDeclaredField("age");         ageField.setAccessible(true);          ageField.setInt(user, 30);                  System.out.println(user);      } }
 
  | 
2. 方法调用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class ReflectMethodDemo {     public static void main(String[] args) throws Exception {         Class<User> clazz = User.class;         User user = clazz.getConstructor(String.class, int.class)                        .newInstance("李四", 28);                           Method method = clazz.getDeclaredMethod("privateMethod", String.class);         method.setAccessible(true);         Object result = method.invoke(user, "参数");                  System.out.println("方法返回值: " + result);     } }
 
  | 
3. 构造方法实例化对比
| 方式 | 代码示例 | 特点 | 
|---|
| newInstance() | User user = User.class.newInstance(); | 只能调用无参构造,已废弃 | 
| Constructor | Constructor<User> c = User.class.getConstructor(String.class, int.class);<br>User user = c.newInstance("王五", 30); | 推荐方式,支持有参构造 | 
三、动态代理机制
1. JDK 动态代理
特点:
- 基于接口实现
 java.lang.reflect.Proxy 生成代理类- 需要实现 
InvocationHandler 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | public class JdkProxyDemo {     public static void main(String[] args) {         UserService realService = new UserServiceImpl();                           UserService proxy = (UserService) Proxy.newProxyInstance(             realService.getClass().getClassLoader(),             realService.getClass().getInterfaces(),             (proxy1, method, args1) -> {                 System.out.println("前置处理");                 Object result = method.invoke(realService, args1);                 System.out.println("后置处理");                 return result;             });                  proxy.addUser("test");      } }
 
  | 
2. CGLIB 动态代理
特点:
- 基于类继承
 - 不需要接口
 - Spring AOP 默认使用
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | public class CglibProxyDemo {     public static void main(String[] args) {         Enhancer enhancer = new Enhancer();         enhancer.setSuperclass(UserServiceImpl.class);         enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {             System.out.println("CGLIB前置处理");             Object result = proxy.invokeSuper(obj, args1);             System.out.println("CGLIB后置处理");             return result;         });                  UserService proxy = (UserService) enhancer.create();         proxy.addUser("test");     } }
 
  | 
3. 两种代理对比
| 特性 | JDK 动态代理 | CGLIB 代理 | 
|---|
| 代理方式 | 接口实现 | 类继承 | 
| 依赖 | 无需额外库 | 需要cglib库 | 
| 性能 | 调用快,创建慢 | 创建快,调用稍慢 | 
| 限制 | 必须实现接口 | 不能代理final类/方法 | 
| 适用场景 | 接口明确的场景 | 无接口或需要高性能 | 
四、注解解析技术
1. 运行时注解处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation {     String value() default "";     int priority() default 0; }
 
  public class AnnotationProcessor {     public static void processAnnotations(Object obj) {         Class<?> clazz = obj.getClass();         for (Method method : clazz.getDeclaredMethods()) {             if (method.isAnnotationPresent(MyAnnotation.class)) {                 MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);                 System.out.println("发现注解方法: " + method.getName());                 System.out.println("注解值: " + annotation.value());                 System.out.println("优先级: " + annotation.priority());             }         }     } }
 
  | 
2. Spring 风格注解解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   |  @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Autowired { }
 
  public class DIContainer {     public static <T> T getInstance(Class<T> clazz) throws Exception {         T instance = clazz.getDeclaredConstructor().newInstance();                           for (Field field : clazz.getDeclaredFields()) {             if (field.isAnnotationPresent(Autowired.class)) {                 Object fieldInstance = getInstance(field.getType());                 field.setAccessible(true);                 field.set(instance, fieldInstance);             }         }         return instance;     } }
 
  | 
3. 编译时注解处理(APT)
定义注解处理器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | @SupportedAnnotationTypes("com.example.MyAnnotation") @SupportedSourceVersion(SourceVersion.RELEASE_11) public class MyAnnotationProcessor extends AbstractProcessor {          @Override     public boolean process(Set<? extends TypeElement> annotations,                           RoundEnvironment roundEnv) {         for (Element element : roundEnv.getElementsWithAnnotation(MyAnnotation.class)) {                          if (element.getKind() == ElementKind.METHOD) {                 ExecutableElement method = (ExecutableElement) element;                 String methodName = method.getSimpleName().toString();                 processingEnv.getMessager().printMessage(                     Diagnostic.Kind.NOTE, "发现注解方法: " + methodName);             }         }         return true;     } }
 
  | 
注册处理器(META-INF/services/javax.annotation.processing.Processor)
五、反射性能优化
1. 缓存反射对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | public class ReflectionCache {     private static final Map<Class<?>, Method> methodCache = new ConcurrentHashMap<>();          public static Object invokeMethod(Object obj, String methodName, Object... args)              throws Exception {         Class<?> clazz = obj.getClass();         Method method = methodCache.computeIfAbsent(clazz,              c -> Arrays.stream(c.getDeclaredMethods())                      .filter(m -> m.getName().equals(methodName))                      .findFirst()                      .orElseThrow());                  method.setAccessible(true);         return method.invoke(obj, args);     } }
 
  | 
2. MethodHandle(Java 7+)
1 2 3 4 5 6 7 8 9 10 11
   | public class MethodHandleDemo {     public static void main(String[] args) throws Throwable {         MethodHandles.Lookup lookup = MethodHandles.lookup();         MethodType type = MethodType.methodType(void.class, String.class);         MethodHandle handle = lookup.findVirtual(User.class, "setName", type);                  User user = new User();         handle.invokeExact(user, "张三");         System.out.println(user.getName());     } }
 
  | 
3. 性能对比(纳秒级操作)
| 操作方式 | 首次调用 | 缓存后调用 | MethodHandle | 
|---|
| 直接调用 | 2-5 ns | - | - | 
| 反射调用 | 1000-2000 ns | 500-1000 ns | 50-100 ns | 
六、安全注意事项
权限控制:
1 2 3 4 5
   |  SecurityManager sm = System.getSecurityManager(); if (sm != null) {     sm.checkPermission(new ReflectPermission("suppressAccessChecks")); }
 
  | 
防御措施:
- 限制反射可访问的包路径
 - 对敏感方法添加额外权限检查
 - 使用
setAccessible()后及时恢复原状态 
最佳实践:
1 2 3 4 5 6 7 8
   | Field field = clazz.getDeclaredField("secret"); boolean accessible = field.isAccessible(); try {     field.setAccessible(true);      } finally {     field.setAccessible(accessible);  }
 
  | 
七、典型应用场景
框架开发:
- Spring IOC 容器
 - JPA/Hibernate ORM 映射
 - JUnit 测试框架
 
动态功能:
工具类:
- BeanUtils 属性拷贝
 - 通用DAO实现
 - 动态SQL生成
 
通过合理使用反射机制,可以实现高度灵活的系统架构,但需要注意性能开销和安全风险。