Spring容器源码解析(二)
前言
在上一篇内容中我们讲解了Spirng容器初始化如何加载工厂和如何判断需要加载的bean是否在容器的流程,这篇内容我们解析一下
1.工厂是如何创建的,BeanFactory体系
2.讲解一下我们接受的ApplicationContext接口接收的体系,ApplicationContext
准备工作
这里需要下载插件
PlantUML integration
BeanFactory体系
然后查看DefaultListableBeanFactory
类右键Diagrams–>show Diagrams查看结构图
4级接口体系
- 第一级:
BeanFactory
作为一个主接口不继承任何接口,暂且称为一级接口。 - 第二级:
AutowireCapableBeanFactory
、HierarchicalBeanFactory
、ListableBeanFactory
3个子接口继承了
它,进行功能上的增强。这3个子接口称为二级接口。 - 第三级:
ConfigurableBeanFactory
可以被称为三级接口,对二级接口HierarchicalBeanFactory
进行了再次
增强,它还继承了另一个外来的接口SingletonBeanRegistry
- 第四级:ConfigurableListableBeanFactory 是一个更强大的接口,继承了上述的所有接口,无所不包,称为
四级接口。
为什么要多层次分割为4个接口?
接口隔离原则(ISP)原则,就是一个接口负责一个单一职责 ,采取多实现接的方式灵活组装类
查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在Spring内部。 在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。
4个接口的作用:
- BeanFactory:是Spring bean容器的根接口。最主要
的方法就是getBean(String beanName),提供获取bean,是否包含bean,是否单例与原型,获取bean类
型,bean 别名的api。 - AutowireCapableBeanFactory: 提供工厂的装配功能。 |
- HierarchicalBeanFactory :提供父容器的访问功能。及父类标注了特性,子类也能得到特性
- ConfigurableBeanFactory 如名,提供factory的配置功能,通过XML文件加载Bean文件的能力
- ConfigurableListableBeanFactory 集大成者,提供解析,修改bean定义,并初始化单例。
- ListableBeanFactory 提供容器内bean实例的枚举功能.这边不会考虑父容器内的实例。
继承关系的2个抽象类和2个实现类
AbstractBeanFactory
作为一个抽象类,实现了三级接口ConfigurableBeanFactory
大部分功能。AbstractAutowireCapableBeanFactory
同样是抽象类,继承自AbstractBeanFactory
,并额外实现了二级接口AutowireCapableBeanFactory
。自动注入Bean
功能DefaultListableBeanFactory
继承自AbstractAutowireCapableBeanFactory
,实现了最强大的四级接口ConfigurableListableBeanFactory
,并实现了一个外来接口BeanDefinitionRegistry
,它并
非抽象类。(DefaultListableBeanFactory
这里就是我们在初始化GenericApplicationContext
时初始化的BeanFactory
工厂对象,继承了4级接口实现了配置,GetBean
,自动加载等方法 )- 最后是最强大的
XmlBeanFactory
,继承自DefaultListableBeanFactory
,重写了一些功能,使自己
更强大(Spring3.1版本后就使用DefaultListableBeanFactory
类替代了)
为什么要使用2个抽象类和2个实现类来实现
依赖倒置原则(Dependence Inversion Principle)
依赖什么?依赖于抽象类
倒置什么?将本类实现的核心代码交给抽象类,本末倒置
将一些资源加载核心资源放到抽象类当中,实现类负责加工。
Spring中有两种容器
- BeanFactory 一个最简单的Spring容器,给依赖注入(DI)提供了基础的支持。
- ApplicationContext 此容器添加以一些企业需要用到的东西,更加全面。它包含了BeanFactory容器
中的东西。
到了这里我们了解清楚各个类中是做什么的就知道了在GenericApplicationContext
初始化流程制造了创建了那些东西,分别是基础类加载,自动注解注入,子父级注解,配置读取类工厂构建成了BeanFactory工厂
ApplicationContext
加载注解
ApplicationContext context =
new AnnotationConfigApplicationContext("org.example.mvc");
理清楚DefaultListableBeanFactory类后我们回头看applicationContext类的实现,本质就是实现了4级接口的所有方法和查看父类是否有注解的工厂方法
ApplicationContext体系
ConfigurableApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext,
Lifecycle, Closeable {
// 配置路径的分隔符
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
//设置此应用程序上下文的唯一ID。
void setId(String id);
//设置父容器,设置后不能再改了
void setParent(@Nullable ApplicationContext parent);
//设置environment 此处为ConfigurableEnvironment 也是可以配置的应用上下文
void setEnvironment(ConfigurableEnvironment environment);
// 此处修改父类返回值为ConfigurableEnvironment
@Override
ConfigurableEnvironment getEnvironment();
//添加一个新的BeanFactoryPostProcessor(refresh()的时候会调用的)
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
// 添加一个事件监听器
void addApplicationListener(ApplicationListener<?> listener);
// 注册协议处理器 允许处理额外的资源协议
void addProtocolResolver(ProtocolResolver resolver);
//加载或刷新配置的持久表示 最最最重要的一个方法
//表示可以是xml、可以是注解、可以是外部资源文件等等。。。。
// 这个方法执行完成后,所有的单例Bean都已经被实例化,Bean工厂肯定也就被创建好了
void refresh() throws BeansException, IllegalStateException;
//JVM运行时注册一个关闭挂钩,在关闭JVM时关闭此上下文,除非此时已经关闭
void registerShutdownHook();
//关闭此应用程序上下文,释放实现可能持有的所有资源和锁 包括一些销毁、释放资源操作
@Override
void close();
//标识上下文是否激活 refresh()后就会激活
boolean isActive();
// 返回此上下文内部的Bean工厂,可以用来访问底层工厂的特定功能。通过此工厂可以设置和验证所需
的属性、自定义转换服务
// 备注:父类方法为获得AutowireCapableBeanFactory接口,而此处的
ConfigurableListableBeanFactory可配置、可列出Bean的工厂是它的子类
ConfigurableListableBeanFactory getBeanFactory() throws
IllegalStateException;
}
这个类在之前的方法中也提到过,主要是增强配置类,比如后置器之类的
GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
............
}
这个类已经不是抽象类了,我们可以直接使用它。但是这个类有一个很大的缺点,因为他没有继承实现AbstractXmlApplicationContext
在AbstractXmlApplicationContext
当中有一个,它不能读取配置的方法loadBeanDefinitions
,需要我们手动去指定读取的方式及位置。但是它依旧有初始化了工厂,我们可以手动设置的注入Bean文件。因为不常用就不演示了。
AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext extends GenericApplicationContext
implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
.......
}
通过 AnnotatedBeanDefinitionReader
注册配置类,用 ClassPathBeanDefinitionScanner
扫描
配置类上申明的路径,得到所有的BeanDefinition
。然后其余的没啥了。这个我们经常使用,因为不用再需要xml文件了,使用 @Configuration 配置类即可,更加的方便。
文章总结
主要梳理了各个类直接的作用,是如何协同操作的,然后讲解了一下,Spring(一)里构造工厂的beanFactory是如何去构造的构造AnnotationConfigApplicationContext
的时候会去构造父类的GenericApplicationContext
构造函数,构造函数创建BeanFactory体系构建工厂,因为没有继承xmlapllicationcontext
所以需要手动注入,因此实现了BeanDefinitionRegistry
方法,构建好工厂后,创建基础扫描后置构造器。构建AnnotatedBeanDefinitionReader
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
第一步reader构建过程了解后,我们了解下一步,scanner的构造过程
后面我们讲解AnnotationConfigApplicationContext
中Scanner扫描的构建过程
熟记各个类直接的关系和作用!!!