0. IOC基本原理
建议不要硬着头皮看Spring代码,本身代码800多m,就是不上班开始看,也不知道什么时候看完,如果想学学IOC,控制反转这些建议看看jodd项目,比较简练,但是我仍然不建议过多看这些框架的代码,因为这些代码要完成任务需要很多琐碎的类实现,比如读取某个包下的所有类,解析class的头文件,反射各种信息,再加上封装。很有可能读源码的过程中掉在各种细节出不来,所以读这种源码不必事无巨细,理解原理即可。
基本原理其实就是通过反射解析类及其类的各种信息,包括构造器,方法及其参数,属性。然后将其封装成bean
定义信息类、constructor
信息类、method
信息类、property
信息类,最终放在一个map
中,也就是所谓的container
,池等等,其实就是个map
。
- 当你写好配置文件,启动项目后,框架会按照你的配置文件找到那个要scan的包,
- 然后解析包里面的所有类,找到所有
@bean
、@service
等注解的类,利用反射解析它们,包括解析构造器,方法,属性等,然后封装成各种信息类到一个map里 - 每当你需要一个
bean
的时候,框架就会从container
找到是不是有这个类的定义。如果找到就通过构造器new出来(这就是控制反转,不用你new,框架帮你new) - 再在这个类找是不是有要注入的属性或者方法,比如标有
@autowrite
的属性,如果有则还是到container
找对应的解析类,new出对象,并通过之前解析出来的信息类找到setter
方法,然后用该方法注入对象(这就是依赖注入)。 - 如果其中有一个类
container
里没找到,则抛出异常,比如常见的spring
无法找到该类定义,无法wire的异常。 - 还有就是嵌套bean则用了一下递归,
container
会放到servletcontext
里面,每次reQuest
从servletcontext
找这个container
即可,不用多次解析类定义。 - 如果
bean
的scope
是singleton
,则会重用这个bean不会再重新创建,将这个bean
放到一个map里,每次用都先从这个map里面去找。 - 如果
scope
是session
,则该bean
会放到session
里面,仅此而已。
1. 说明
IOC是Spring中核心功能之一,基本原理就是通过反射解析类及其各种信息,然后封装成对象,存放在map中,即bean容器。可以根据其基本原理简单实现一个Spring IOC模块,完整代码见文末链接。
模拟同学会面的打招呼场景,定义
Greeting
接口,包含hello
方法,实现对某人打招呼Hello
类实现该Greeting
接口,实现hello
方法。然后定义人类Person
的抽象类,具备属性name
,Student
为该类的继承类。同时还包括BeanFactory
接口,以及负责xml文件解析与bean
创建等
2. 基本类
1 | /** |
- 上述代码中,学生服务类中的
helloService
方法,表示调用greeting
的方法,完成对某个打招呼的功能,这里依赖于另外一个对象Person
类,这样的依赖注入,通过IOC来实现
3. 配置解析与容器类
1 | /** |
4. xml配置文件
1 |
|
5. 功能测试
1 | public class StudentServiceTest { |
6. 运行结果
1 | hello : ioc.Hello |