Spring IOC知识点总结
IOC容器中的核心角色
BeanFactory
BeanFactory接口是Spring IOC中的一个核心接口,提供了IOC容器的基本实现,用于管理和创建Bean,即IOC容器是基于BeanFactory接口实现的。BeanFactory接口的主要功能有获取Bean、检索IOC容器中是否包含Bean、判断Bean是否是单例等。BeanFactotory主要负责Bean的加载、实例化、维护Bean之间的依赖关系、负责Bean的生命周期。
下面我们来看下BeanFactory接口的主要继承结构。
从上图我们可以看到BeanFactory
接口下有三个子接口ListableBeanFactory
、HierachicalBeanFactory
、AutowireCapableBeanFactory
。这三个子接口分别应用于不同的场景Listable可以获取多个Bean,最顶层的BeanFactory都是获取单个Bean;Hierachical主要用来处理BeanFactory的父子关系,可以获得BeanFactory的父工厂;AutowireCapable主要用来自动装配Bean的。
从图中我们发现BeanFactory经过一系列的继承最终由DefaultListableBeanFactory
这个子类全部继承,即DefaultListableBeanFactory
类拥有BeanFactory的全部功能,是BeanFactory的集大成者,在Spring IOC中也是由DefaultListableBeanFactory
类来实现IOC容器。
BeanFactory和FactoryBean的区别
BeanFactory是一个工厂类,用于管理和创建Bean的工厂。
FactoryBean是一个Bean,也是一个接口。实现了该接口的类,通过容器获取Bean,返回的不是他们本身,而是接口getObject方法中生产的实例。例如当一个类ABean实现了FactoryBean,通过容器使用getBean(String beanName),即applicationContext.getBean(“aBean”),返回的不是aBean对象,而是aBean实现getObject中生成的实例。如果要返回它本身需要在beanName前面加上“&”,即applicationContext.getBean("&aBean")。
ApplicationContext
ApplicationContext
接口继承了众多接口,为Spring
的运行提供基本的功能支撑。这里我们主要讲它与BeanFactory
之间的关系,前面我们讲到了BeanFactory
,从BeanFactory
的继承体系中我们可以看到AppicationContext
接口继承了BeanFactory
的ListableBeanFactory
接口和HierarchicalBeanFactory
接口,从这里我们就可以只知道ApplicationContext就是一个BeanFactory,具有BeanFactory的所有功能。你可能想说ApplicatoinContext
接口并没有继承AutowireCapableBeanFactory
接口,这个不需要担心,在它的抽象实现类(AbstractRefreshableApplicationContext
)中依赖了一个BefaultListableBeanFactory
,这样ApplicationContext
就具有了BeanFactory
的全部功能。下面我们来看下ApplicationContext
接口的继承结构,常用的类有ClassPathXmlApplicationContext
和FileSystemXmlApplicationContext
以及AnnotationConfigApplicationContext
。
BeanDefinition
Spring可以说是面向Bean编程,将对象以Bean的形式注入到Spring容器中,而每一个Bean(对象)的类型,依赖关系,字段等信息都不一样,那么怎么做到统一管理Bean呢?在Spring中就用到了BeanDefinition
这个概念来实现对Bean的包装,从而使的Spring能够统一管理Bean。
BeanDefinition
中记录了和Bean相关的所有信息,如是否是单例、作用范围、依赖关系、BeanName等。
从上图我们可以看到BeanDefinition
主要继承了AttributeAccessor
接口和BeanMetadataElement
接口。AttributeAccessor
主要用来操作Bean的元数据。BeanMetadataElement
主要用来获取当前元素的配置源bean对象。
BeanWrapper
BeanWrapper是Bean的包装类,即在内部会保存Bean的实例,并提供其他一些扩展功能。同时,BeanWrapper接口还继承了PropertyAccessor, propertyEditorRegistry, TypeConverter、ConfigurablePropertyAccessor接口,所以它还提供了访问bean的属性值、属性编辑器注册、类型转换等功能。通过BeanWrapper,Spring IOC可以用统一的方式来访问Bean的属性。
Spring IOC容器的启动过程
Bean加载
1、ResourceLoad根据路径加载(xml)配置文件,并将配置文件转化成Resource对象。
2、BeanDefinitionReader将配置文件中的配置转换成Spring能够识别的BeanDefinition注册到BeanFactory中。
BeanDefinitionReader加载Bean的详细步骤(loadBeanDefinitionf方法)
1、DocumentLoader将Resource文件转化成Document对象。
2、BeanDefinitionDocumentReader解析Document对象,将配置文件中的配置解析成Spring可以识别的BeanDefinition。
3、通过BeanDefinitionRegistry将BeanDefinition注册到Spring的IOC容器中(默认是DefaultListableBeanFactory作为IOC容器)
Bean初始化
要注意的是虽然上面我们已经将Bean加载到IOC容器中,但是此时的Bean是没有初始化的。Bean的初始化实在getBean的时候执行。
1、根据BeanName去获取Bean实例,判断是否是单例Bean,是的话则从缓存中获取,没有再去创建,不是单例Bean则直接创建。
2、在创建Bean之前,先根据BeanName去我们的IOC容器中获取BeanDefinition。
3、根据BeanDefinition获取Bean所有的依赖关系,根据依赖关系,先创建被依赖的Bean。
4、被依赖的Bean创建好之后则是根据BeanDefinition创建Bean实例。
创建Bean实例的具体步骤:
1、根据BeanDefinition通过反射创建Bean的实例,注意此时的Bean还没有设置属性。
2、将创建好的Bean实例用BeanWrapper封装。
Definition通过反射创建Bean的实例,注意此时的Bean还没有设置属性。
2、将创建好的Bean实例用BeanWrapper封装。
3、根据BeanDefinition给Bean实例注入属性(即依赖注入)。