16-Java反射机制:Spring IOC背后的核心技术

发布时间:2026/7/17 0:57:55
16-Java反射机制:Spring IOC背后的核心技术 Java反射机制Spring IOC背后的核心技术开篇为什么框架能自动创建对象你有没有想过Spring里你只写了一个Service注解Spring就能自动创建对象、注入依赖、调用方法。它是怎么做到的答案就是反射。反射是Java的自省能力让程序在运行时能查看和操作自己的结构。本文不讲高深理论只讲反射的核心用法和实际应用场景。一、什么是反射反射Reflection是指在运行状态中程序可以获取任意一个类的内部信息并且可以操作它的属性、方法、构造器。正常情况下我们写代码是知道类名直接new对象。反射则是只知道类名字符串也能创建对象并调用方法。// 传统方式知道类名UserusernewUser();// 反射方式只知道类名字符串Class?clazzClass.forName(com.example.User);Objectuserclazz.newInstance();【面试高频】反射让Java从静态语言具备了一定的动态性。二、获取Class对象的三种方式Class对象是反射的入口。获取Class对象有三种方式// 方式一类名.classClassUserclazz1User.class;// 方式二对象.getClass()UserusernewUser();Class?clazz2user.getClass();// 方式三Class.forName()Class?clazz3Class.forName(com.example.User);一个类在JVM中只有一个Class对象。无论用哪种方式获取比较结果都是true。System.out.println(clazz1clazz2);// trueSystem.out.println(clazz2clazz3);// true三、反射操作构造器3.1 获取构造器Class?clazzUser.class;// 获取所有public构造器Constructor?[]constructorsclazz.getConstructors();// 获取指定参数类型的构造器Constructor?constructorclazz.getConstructor(String.class,int.class);3.2 创建对象Constructor?constructorclazz.getConstructor(String.class,int.class);Objectuserconstructor.newInstance(张三,20);【面试高频】Class.newInstance()在JDK9之后被标记为过时推荐使用Constructor.newInstance()。四、反射操作方法4.1 获取方法Class?clazzUser.class;// 获取所有public方法包括继承的Method[]methodsclazz.getMethods();// 获取指定方法MethodsetNameclazz.getMethod(setName,String.class);4.2 调用方法Objectuserclazz.newInstance();MethodsetNameclazz.getMethod(setName,String.class);setName.invoke(user,李四);invoke的第一个参数是方法所属的对象后面的参数是方法实参。4.3 调用私有方法MethodprivateMethodclazz.getDeclaredMethod(privateMethod);privateMethod.setAccessible(true);// 暴力破解访问权限privateMethod.invoke(user);五、反射操作字段5.1 获取字段Class?clazzUser.class;// 获取所有public字段Field[]fieldsclazz.getFields();// 获取指定字段FieldnameFieldclazz.getDeclaredField(name);5.2 修改字段值Objectuserclazz.newInstance();FieldnameFieldclazz.getDeclaredField(name);nameField.setAccessible(true);nameField.set(user,王五);Stringname(String)nameField.get(user);System.out.println(name);// 王五六、反射的典型应用场景6.1 Spring IOC容器Spring通过反射读取配置文件或注解自动创建Bean对象// 配置文件bean iduserServiceclasscom.example.UserService/// Spring底层Class?clazzClass.forName(com.example.UserService);Objectbeanclazz.newInstance();6.2 MyBatis结果集映射MyBatis查询数据库后通过反射把数据库字段映射到Java对象属性Fieldfieldclazz.getDeclaredField(columnName);field.setAccessible(true);field.set(obj,resultSet.getObject(columnName));6.3 JDBC加载驱动Class.forName(com.mysql.cj.jdbc.Driver);这行代码就是利用反射把数据库驱动类加载到内存。6.4 序列化与反序列化JSON框架如FastJSON、Jackson通过反射读取对象字段把对象转成JSON字符串或者把JSON字符串转成对象。七、手写简易IOC容器下面用反射实现一个极简版IOC容器让你理解Spring的核心原理。7.1 定义注解Retention(RetentionPolicy.RUNTIME)Target(ElementType.TYPE)publicinterfaceMyComponent{Stringvalue()default;}7.2 标注BeanMyComponentpublicclassUserService{publicvoidsayHello(){System.out.println(Hello from UserService);}}7.3 IOC容器publicclassMyIocContainer{privateMapString,ObjectbeanMapnewHashMap();publicvoidscan(StringpackageName)throwsException{// 简单起见直接加载指定类Class?clazzClass.forName(packageName);if(clazz.isAnnotationPresent(MyComponent.class)){Objectbeanclazz.newInstance();StringbeanNameclazz.getSimpleName();beanNamebeanName.substring(0,1).toLowerCase()beanName.substring(1);beanMap.put(beanName,bean);}}publicObjectgetBean(Stringname){returnbeanMap.get(name);}}7.4 使用容器publicclassIocDemo{publicstaticvoidmain(String[]args)throwsException{MyIocContainercontainernewMyIocContainer();container.scan(com.example.UserService);UserServiceuserService(UserService)container.getBean(userService);userService.sayHello();}}【面试高频】Spring IOC的核心就是通过反射创建对象并管理对象生命周期。八、反射的优缺点8.1 优点可以在运行时动态创建对象可以操作私有成员是框架实现的基础8.2 缺点性能比直接调用低破坏了封装性代码可读性下降【面试陷阱】反射性能差不是绝对的。JDK对反射做了很多优化普通场景下差距不大。但在高并发、大量反射调用的场景要注意。九、开发踩坑实录坑 1Class.forName类名写错Class?clazzClass.forName(com.example.user);// 类名大小写错误后果ClassNotFoundException。正确做法类名必须是完整限定名且大小写一致。坑 2调用私有成员没setAccessibleFieldfieldclazz.getDeclaredField(name);field.set(user,张三);// 报 IllegalAccessException正确做法先调用field.setAccessible(true)。坑 3反射创建对象时无参构造器被删除publicclassUser{publicUser(Stringname){}// 只有有参构造器}UseruserUser.class.newInstance();// 报错正确做法明确调用对应参数的构造器。坑 4invoke参数类型不匹配Methodmethodclazz.getMethod(setAge,int.class);method.invoke(user,20);// 参数类型不匹配正确做法传入与声明类型一致的实际参数。坑 5反射滥用导致代码难以维护反射虽然强大但过度使用会让代码变成黑魔法。普通业务代码中应优先使用正常面向对象写法。十、面试速记卡10.1 核心API速查API作用Class.forName()加载类并获取Class对象clazz.newInstance()创建对象JDK9后过时getConstructor()获取构造器getMethod()获取方法getField()获取public字段getDeclaredMethod()获取任意方法含私有getDeclaredField()获取任意字段含私有setAccessible(true)暴力破解访问权限invoke()调用方法10.2 高频面试题什么是反射有什么作用获取Class对象的三种方式是什么反射如何调用私有方法Spring IOC底层是怎么实现的反射的优缺点是什么为什么反射性能比直接调用低JDBC中Class.forName()的作用是什么10.3 口诀总结反射入口是Class三种方式获取它 forName最常用全限定名别写差 构造器和方法都能反射拿 私有成员加setAccessible才能操作它 框架底层爱用它Spring IOC靠它发 反射虽好别滥用代码维护会抓瞎十一、小结反射是Java最强大的特性之一也是大多数框架的底层基础。掌握反射的核心API、理解Spring IOC的实现原理、能手写一个简易容器面试和工作都够用了。记住反射是一把双刃剑能解决问题但不要为了用而用。