Loading... ## 1.反射的定义 反向探知,在程序运行过程中动态的获取类的相关属性 > 这种动态获取类的内容以及动态调用对象的方法和获取属性的机制.就叫做JAVA的反射机制 反射的优缺点 > 优点 > > 增加程序的灵活性,避免固有逻辑写死到程序中 > > 代码相对简洁,可以提高程序的复用性 > 缺点 > > 相比于直接调用反射有比较大的性能销毁 > > 内部暴露和安全隐患 反射到底慢在哪里? > 1.调用了native方法 > > 2.每次newInstance都会做安全检查 比较耗时 ## 2.反射的操作 ### 2.1基本操作 #### 1.获取类对象的四种方式 ```java // 获取类对象的四种方式 Class<User> clazz1 = User.class; Class<?> clazz2 = Class.forName("jupiter.fs.User"); Class<? extends User> clazz3 = new User().getClass(); Class<?> clazz4 = Demo.class.getClassLoader().loadClass("jupiter.fs.User"); ``` #### 2.基本信息操作 ```java // 获取类的相关结构 System.out.println(clazz1.getModifiers()); // 获取类的修饰符 System.out.println(clazz1.getPackage()); System.out.println(clazz1.getName()); System.out.println(clazz1.getSuperclass()); System.out.println(clazz1.getClassLoader()); System.out.println(clazz1.getSimpleName()); System.out.println(clazz1.getInterfaces().length); // 获取类似实现的所有的接口 System.out.println(clazz1.getAnnotations().length); ``` ### 2.2字段的操作 ```java /** * Field操作 * @param args */ public static void main(String[] args) throws Exception { Class<User> userClass = User.class; // 获取User对象 User user = userClass.newInstance(); // 获取类型中定义的字段 共有的字段以及父类中共有的字段 Field[] fields1 = userClass.getFields(); for(Field f:fields1){ System.out.println(f.getModifiers() + " " + f.getName()); } System.out.println("--------------------"); // 可以获取私有的字段 只能够获取当前类中 Field[] fields2 = userClass.getDeclaredFields(); for(Field f:fields2){ System.out.println(f.getModifiers() + " " + f.getName()); } // 获取name字段对应的Field Field nameField = userClass.getDeclaredField("name"); // 如果要修改私有属性信息那么我们需要放开权限 nameField.setAccessible(true); nameField.set(user,"jupiter"); System.out.println(user.getName()); // 如果对静态属性赋值 Field addressField = userClass.getDeclaredField("address"); addressField.set(null,"上海"); System.out.println(User.address); } ``` ### 2.3 类中的方法操作 ```java public static void main(String[] args) throws Exception { User user = new User(); Class<User> userClass = User.class; // 可以获取当前类及其父类中的所有的共有的方法 Method[] methods = userClass.getMethods(); for (Method m : methods) { System.out.println(m.getModifiers() + " " + m.getName()); } System.out.println("**********"); // 获取本类中的所有的方法 包括私有的 Method[] declaredMethods = userClass.getDeclaredMethods(); for (Method m:declaredMethods){ System.out.println(m.getModifiers() + " " + m.getName()); } Method jumpMethod = userClass.getDeclaredMethod("jump"); // 放开私有方法的调用 jumpMethod.setAccessible(true); jumpMethod.invoke(user); Method sayMethod = userClass.getDeclaredMethod("say", String.class); // 静态方法调用 sayMethod.invoke(null,"Jupiter666"); } ``` ### 2.4 构造器的操作 ```java /** * 构造器的操作 * @param args */ public static void main(String[] args) throws Exception { Class<User> userClass = User.class; // 获取所有的公有的构造器 Constructor<?>[] constructors = userClass.getConstructors(); for (Constructor c:constructors){ System.out.println(c.getModifiers() + " " + c.getName() ); } System.out.println("************************"); // 获取所有的构造器 Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors(); for (Constructor c:declaredConstructors){ System.out.println(c.getModifiers() + " " + c.getName() ); } // 1.直接通过newInstance创建对象 User user = userClass.newInstance(); // 2.获取对应的Construcator对象获取实例 Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class); // 私有的构造器调用需要放开权限 declaredConstructor.setAccessible(true); System.out.println(declaredConstructor.newInstance("jupiter","男")); } ``` ## 3.单例的漏洞 产生的原因是:反射可以调用私有的构造器造成的 ```java public class PersonSingle { private static PersonSingle instance; private PersonSingle(){ if(instance != null){ throw new RuntimeException("实例已经存在了,不允许再创建..."); } } public static PersonSingle getInstance(){ if(instance == null){ instance = new PersonSingle(); } return instance; } } ``` 解决方案:在私有构造其中加入逻辑判断结合`RuntimeException`处理即可 ```java public static void main(String[] args) throws Exception { PersonSingle p1 = PersonSingle.getInstance(); PersonSingle p2 = PersonSingle.getInstance(); PersonSingle p3 = PersonSingle.getInstance(); System.out.println(p1); System.out.println(p2); System.out.println(p3); // 通过反射获取实例 Constructor<? extends PersonSingle> declaredConstructor = p1.getClass().getDeclaredConstructor(); declaredConstructor.setAccessible(true); System.out.println( declaredConstructor.newInstance()); } ``` 反射的使用场景: 1.jdbc封装 2.SpringIoC 3.JdbcTemplate 4.Mybatis .... ## 4.反射的应用 SpringIoC IoC 控制反转 就是一种设计思想,容器 管理对象 ```java try { // 创建对应IoC容器对象 DefaultListableBeanFactory beanFactory = this.createBeanFactory(); beanFactory.setSerializationId(this.getId()); this.customizeBeanFactory(beanFactory); // 配置文件中的<bean> 会被解析封装为一个 BeanDefinition this.loadBeanDefinitions(beanFactory); Object var2 = this.beanFactoryMonitor; synchronized(this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException var5) { throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); } ``` ```java // 加载配置问题 SAX Document doc = this.doLoadDocument(inputSource, resource); // 配置文件解析 BeanDefinition return this.registerBeanDefinitions(doc, resource); ``` ```java public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); // 创建IoC容器对象 BeanFactory 同时解析配置文件 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); // 单例对象的实例化 this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } } ``` ```java public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { ReflectionUtils.makeAccessible(ctor); return ctor.newInstance(args); } catch (InstantiationException var3) { throw new BeanInstantiationException(ctor, "Is it an abstract class?", var3); } catch (IllegalAccessException var4) { throw new BeanInstantiationException(ctor, "Is the constructor accessible?", var4); } catch (IllegalArgumentException var5) { throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", var5); } catch (InvocationTargetException var6) { throw new BeanInstantiationException(ctor, "Constructor threw exception", var6.getTargetException()); } } ``` Last modification:November 17, 2021 © Allow specification reprint Support Appreciate the author Like 0 欢迎留下您的脚印