在编程语言中,反射是一个绕不过的一个话题,反射、注解、动态代理是支撑框架运行的核心技术。
在Spring中,IOC利用反射实现,创建对象。AOP利用动态代理实现,实现切面编程,配置利用注解实现。所以继上一篇,注解,本篇来讲解一下反射。
反射的作用
创建对象
在刚开始学习java的时候,都是直接new对象,但是进入web编程的之后,发现不需要使用自己new对象了,直接在注解上@Bean 就可以在框架运行时进行创建对象,其实就是利用反射创建对象。
new的方式创建对象,其创建对象的需求是在代码编写时确定的,而通过反射来创建对象,是在运行时期来确定的。
执行方法
除了在运行时期动态创建对象,还可以在运行时期动态执行方法,通过 new的方式 只能在编译期确定。这种就需要反射。
获取类信息
通过反射还可以动态获取类的信息,方法,属性等。
用法
Class
Class是一个类,存储的是类的信息,Class提供了大量的方法,可以获取类的信息,比如获取类中的方法,构造函数等。
// 创建Class对象 方式1Class<?> clazz = Class.forName("com.fanshe.FanSheDemo");// 方式2Class<FanSheDemo> sheDemoClass = FanSheDemo.class;// 方式3FanSheDemo fanSheDemo = new FanSheDemo();Class<? extends FanSheDemo> fanSheDemoClass = fanSheDemo.getClass();
当然出了Class、还有Constructor、Method、Field等常用方法。
应用
在平时的开发中,如果我们使用工厂模式,其实可以发现工厂模式中都是直接写死在代码中的。但是对于一个通用型的框架来说,必须高度解耦合。SpringIOC的容器流程就是如下,通过配置文件定义要创建的对象,然后解析成BeanDefition,利用反射创建对象,存储Map中。
从整体代码上看,其实就是通过将对象信息存入BeanDefinitions中,然后创建对象,通过反射的方式,将对象存入到map中。
原理
{ long star = System.currentTimeMillis();for (int i = 0; i < 10000000; i++) {C c = new C();c.f();}System.out.println("new:"+(System.currentTimeMillis() - star));long star2 = System.currentTimeMillis();for (int i = 0; i < 10000000; i++) {Class<C> cClass = C.class;C c = cClass.newInstance();c.f();}System.out.println(System.currentTimeMillis() - star2);}public static class C {public void f() {}}
通过上述代码,可以看到其实反射比new的方式要慢,主要在于反射这种方式多了安全性检查和类,方法的查找。具体这里就不详细描述感兴趣的可以自行查阅相关资料。