第一时间获取技术干货和业界资讯!
☞ 免费CSDN资料帮下服务 | 免费加群 ☜
很多人看过 Spring 的源码,但是他们都是为了看源码而看!并没有读懂 Spring 的设计思想,也没有思考过为什么要这样设计!
我在这篇文章《程序员如何阅读源码?大牛是如果形成的?》中,已经写到了如何阅读源码。而我的同事按照上面的步骤并结合自身的情况,再过去的几个月看了不少的源码。最终今年破格加薪 2K !
那么接下来我呀说的是,有哪些是你在看源码的过程中并没有注意的细节和内容。比如,今天我们要学习的Spring IOC 容器为什么不使用 Class.forName 加载类,而是使用 ClassLoader!
虽然 Class.forName() 和 ClassLoader 都可用来对类进行加载,但是它们还是有些区别的。为了说明它们,我们来看看 JVM 加载类的步骤是什么!
清楚上面这个之后,再要想搞明白 Spring Ioc中为什么使用 Classloader,而不是 Class.forName,还得从它们的区别说起。我们先来看看如果使用 Class.forName 会发生什么!
先创建一个测试类。
上面的代码中, Class.forName("com.xttblog.Xttblog") 的调用会触发 Xttblog 的静态代码块的执行, 而 ClassLoader.getSystemClassLoader().loadClass("com.xttblog.Xttblog") 并不会。
调用 Class.forName 其实相当于调用了 Class.forName(className, true, currentLoader), 这个方法的第二个参数表示是否需要初始化类。源码中设置为 true, 因此 Class.forName 获取到 Class 对象时, 会自动对类进行初始化的。并且 Class.forName 加载类的 ClassLoader 和调用 Class.forName 所在的类的 ClassLoader 相同。上面的代码中, Class.forName("com.xttblog.Xttblog") 的调用会触发 Xttblog 的静态代码块的执行, 而 ClassLoader.getSystemClassLoader().loadClass("com.xttblog.Xttblog") 并不会。
我们知道 Spring 的 IOC 中有一个懒加载(延迟加载),如果你使用了 Class.forName,那么懒加载这个功能就无法实现了。Spring IoC 为了加快初始化速度,因此大量使用了延时加载技术。而使用 classloader 不需要执行类中的初始化代码,可以加快加载速度,把类的初始化工作留到实际使用到这个类的时候。
所以,Spring IOC 容器并没有采用 Class.forName 来加载类。