原文转自我自己的个人公众号:https://mp.weixin.qq.com/s/smZFx6r6P8TXfcii_bI3pg
由于我是从公众号上直接复制粘贴过来的,排版上可能有问题。推荐使用上方连接查看原文。
注意:本系列会持续跟踪SpringFramework的最新版本。当前的最新版本为:5.2.8.RELEASE
注意:文中的类图为了简介,图中的方法都没有标出返回值和参数,不同参数的多个重载方法只写了一个
目录:
-
使用Jar包依赖引入SpringFramework
-
初看ApplicationContext
-
小结一
-
再看ApplicationContext
-
深入BeanFactory
-
小结二
-
ApplicationContext实现类和DefaultListableBeanFactory
-
总结
1. 使用Jar包依赖引入SpringFramework
目前,SpringFramework官方文档中已经没有用Jar包依赖来引入SpringFramework的部分了,取而代之的是使用SpringBoot来引入。但我们这个系列主要是说SpringFramework,因此我们不使用SpringBoot。
-
安装maven:下载地址https://maven.apache.org/download.cgi,下载好解压到相应的目录,具体安装方法见https://maven.apache.org/install.html。
-
配置maven仓库:这一步是可选的。maven默认使用中央仓库,但由于网络问题,拉取依赖可能会比较慢,因此可以构建私服来缓存jar包。一些公司会开放自己的私服供大家使用。这里使用腾讯云的私服。具体方法参见https://cloud.tencent.com/document/product/649/20231。
-
在IDE中配置maven:这里介绍的是在IntelliJ IDEA中配置,如下图
-
创建maven工程:这一步就不细说了。
-
配置POM文件中的依赖:配置编译版本和依赖,如下图
-
编写main方法:如下
-
做完以上的工作,SpringFramework就引入到代码中了。
2. 初看ApplicationContext
在上面最后一步的main方法中只有一行代码,其中就会看到ApplicationContext,那么这是个什么东西呢?我们来看一下它是什么,它又继承自什么?
上图是我画的ApplicationContext继承关系的类图。从图上可以看出,ApplicationContext是一个接口,它之上的顶层接口有BeanFactory、EnvironmentCapable、ApplicationEventPublisher、MessageSource和ResourceLoader。接下来我们就逐一的看看它们都是做什么的。
2.1 我们从简单的开始,首先看一下EnvironmentCapable
该接口提供获取环境变量的能力,Spring中所有的上下文都实现了这个接口。这个接口只有一个方法:
-
Environment getEnvironment():返回代表环境变量的对象。需要注意的是,ApplicationContext的子类ConfigurableApplicationContext对这个方法的返回值进行了重定义,提供了更具体的返回值ConfigurableEnvironment。
2.2 下面来看ApplicationEventPublisher
这个接口的作用是封装了发布事件的功能。SpringFramework内部使用这套事件发布机制实现了观察者模式,通过为相应的事件注册对应的监听者,可以将操作通过事件的形式传播到所有监听者中进行相应处理。该接口也只有一个方法:
-
void publishEvent(Object event):通知所有监听该事件的监听器。接口本身不要求监听器是异步还是同步处理。当传入的参数不是ApplicationEvent接口的子类时,SpringFramework自动将其封装到一个PayloadApplicationEvent类型的对象中。
-
default void publishEvent(ApplicationEvent event):这是接口中的一个默认方法,内部就简单的调用了publishEvent((Object) event),该方法的目的就是能够将event限定为ApplicationEvent类型。
2.3 MessageSource
该接口是一个策略接口,用于处理参数化和国际化的消息。Spring内置两个实现类,ResourceBundleMessageSource底层使用Java自带的ResourceBundle;ReloadableResourceBundleMessageSource拥有更高的可配置性,尤其支持重新加载消息定义。该接口有三个重载的getMessage方法:
-
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale):第一参数code用于查找消息定义。如果没找到就用第三参数指定的默认消息。code推荐使用类的完全限定名或者包名。
-
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException:同上。找不到code会抛异常。
-
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException:同上。用MessageSourceResolvable封装了其它三个参数。
2.4 下面看一个稍微复杂点的接口ResourcePatternResolver
主要的作用是检索符合条件的资源,这里定义了一个常量“classpath*:”,作为表示类路径的前缀,检索范围包括jar包中的条目。这个接口继承自ResourceLoader,其中定义常量“classpath:”用来表示类路径的url前缀。ResourcePatternResolver接口中只有一个方法,但从父接口中继承了两个,统一列在下面:
-
Resource getResource(String location):继承自ResourceLoader。从指定路径加载资源。返回的Resource对象可以重用(可以多次调用getInputStream方法)。路径可以是标准的URL、classpath和相对路径。返回的Resource不保证物理存在,需要使用exists方法确认。
-
ClassLoader getClassLoader():继承自ResourceLoader。返回加载资源的ClassLoader。应用程序应统一使用该ClassLoader,而不是依赖线程上下文的ClassLoader。
-
Resource[] getResources(String locationPattern) throws IOException:ResourcePatternResolver接口自己的方法。返回符合模式的所有资源。应尽可能避免指向同一物理资源的条目重叠。返回结果会去重。
2.5 最复杂的来了!
ApplicationContext继承了HierarchicalBeanFactory和ListableBeanFactory接口,而这两个接口又继承自BeanFactory。这就引出了SpringFramework中另一个核心接口BeanFactory。
ApplicationContext会将Bean的创建和检索等操作委托给BeanFactory来处理。这里的细节我们留到下一部分细说。
2.6 ApplicationContext自己
一个ApplicationContext可以看作就是一个SpringFramework环境。程序中可能会有多个上下文环境。因此这个接口提供了针对该环境的功能,具体方法如下:
-
String getId():获得上下文环境的ID。由子类具体定义ID规则。
-
String getApplicationName():返回该上下文所属的应用名称。
-
String getDisplayName():返回该上下文的显示名称。
-
long getStartupDate():返回该上下文首次被加载时的时间戳。
-
ApplicationContext getParent():返回父上下文。
-
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException:可用于向Spring管理外的对象注入Bean实例。
3. 小结一
至此,我们分析了ApplicationContext接口的继承关系。从继承关系中我们可以看到。ApplicationContext从EnvironmentCapable继承了获取环境变量的能力;从ApplicationEventPublisher继承了发布事件的能力;从MessageSource继承了消息参数化和国际化的能力;从ResourcePatternResolver中继承了从URL、类路径和Jar包中获取资源的能力;并通过继承ListableBeanFactory和HierarchicalBeanFactory获得了BeanFactory中检索Bean实例的能力。而ApplicationContext自身具有维护上下文属性的能力。
4. 再看ApplicationContext
我们已经从ApplicationContext的父接口中分析了它都具有什么样的能力。那么我们继续向继承关系的另一个方向出发,看看又有哪些接口继承了ApplicationContext,以及它们又提供了什么能力。
从上图我们可以看到,ConfigurableApplicationContext继承了ApplicationContext,这个接口同时还继承了Lifecycle和Closeable接口。依照惯例,我们先从简单的接口看起。
4.1 Closeable
Closeable接口是Java中的接口,只有一个close方法,该接口继承自AutoCloseable接口,其实现类可以使用Java7开始支持的try-with-resources方式关闭资源。比较简单,不做过多解释了。
4.2 Lifecycle
提供启动和关闭这两个生命周期控制。可以被组件和容器实现,如果是容器(什么是容器?本文最后会将)实现,则该容器中所有的组件都会收到启动和停止信号。只有顶层的Singleton的Bean支持该声明周期。该接口的子接口SmartLifecycle提供更复杂的控制,比如支持异步停止、自动启动、启动顺序等。这个接口也不过多解释了,就三个方法,看名字都能知道是干什么的。
4.3 重点来了:ConfigurableApplicationContext
从上方的类图可以看出,从这个接口开始,出现了设值方法,对上下文属性进行设置。上面介绍的其它接口都为取值方法。下面我们来逐一看看这些方法的作用:
-
void setId(String id):设置为上下文唯一标识。
-
void setParent(@Nullable ApplicationContext parent):设置上下文的父上下文。
-
void setEnvironment(ConfigurableEnvironment environment):为上下文设置Environment。
-
ConfigurableEnvironment getEnvironment():上面提到过,在
ConfigurableApplicationContext中对其父接口EnvironmentCapable中的getEnvironment()方法返回值进行了窄化。 -
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor):为上下文添加一个BeanFactoryPostProcessor,该处理器可以在刷新时且解析Bean定义之前被使用。做框架或工具包的时候常用。
-
void addApplicationListener(ApplicationListener<?> listener):添加一个监听器,用来接收上下文事件,比如上下文刷新和上下文关闭。这里与之配合的就是ApplicationEvent。
-
void setClassLoader(ClassLoader classLoader):设值加载资源的ClassLoader。
-
void addProtocolResolver(ProtocolResolver resolver):添加额外的协议解析器,主要用于解析URL或其它类型的资源地址。这里添加的解析器会放在所有解析器的前面,因此可以用来覆盖默认的。
-
void refresh() throws BeansException, IllegalStateException:从持久化的配置中加载和刷新上下文。配置可以是基于java的配置类、xml、properties文件和关系型数据库等。
-
void registerShutdownHook():该方法注册一个Hook,可以在jvm关闭的时候关闭该上下文。
-
void close():关闭该上下文,释放该上下文持有的所有资源,包括缓存的所有Singleton的Bean。
-
boolean isActive():判断上下文的状态是否是激活的。激活的含义是至少有一次refresh操作且没有close。
-
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException:这里又引入了另一个非常重要的接口。这里暗示着,ConfigurableApplicationContext的实现类内会引用一个ConfigurableListableBeanFactory的实现类,用来托管所有Bean的创建和管理功能。
5. 深入BeanFactory
上面最后提到ConfigurableApplicationContext接口内的getBeanFactory方法返回ConfigurableListableBeanFactory。下面我们来看看ConfigurableListableBeanFactory的继承关系:
由于ConfigurableBeanFactory接口中的方法太多,上图没有显示这些方法。对比之前ApplicationContext的继承关系,我们可以看到顶层接口都是BeanFactory。
因此这里再次强调一下,BeanFactory本身可以理解为是Bean的容器,负责创建和管理。而ApplicationContext继承了BeanFactory中检索Bean的能力,并且内部持有一个BeanFactory的实现类引用,将Bean的检索和管理都委托给了BeanFactory的实现类。
5.1 BeanFactory
2001年4月13日创建的接口,就是这个20年前创建的接口,撑起了SpringFramework,可见优良设计的重要性。该接口是用于访问Spring Bean容器的最顶层接口。这个工厂的实现类内部保存了Bean的定义,每个Bean都通过一个字符串名称来唯一标识。工厂会根据Bean的定义来返回一个独立的实例(Prototype)或者返回一个在工厂范围内共享的实例(Singleton)。BeanFactory是所有component的注册中心和配置中心。虽然可以通过BeanFactory中的相关方法对指定的Bean进行检索(pull模式),但是更推荐的方式是使用依赖注入(push模式)。Spring的依赖注入的实现使用了BeanFactory和其子接口的能力。BeanFactory从配置源(如:xml)或Java代码中读取Bean定义,然后对其进行配置,BeanFactory本身不关注定义的存储形式,如LDAP,RDBMS,XML,properties文件等。BeanFactory创建的Bean会经过Spring标准的初始化生命周期,如下:
-
BeanNameAware接口的setBeanName方法;
-
BeanClassLoaderAware接口的setBeanClassLoader方法;
-
BeanFactoryAware接口的setBeanFactory方法;
-
EnvironmentAware接口的setEnvironment方法;
-
EmbeddedValueResolverAware接口的setEmbeddedValueResolver方法;
-
ResourceLoaderAware接口的setResourceLoader方法。(只有运行在一个ApplicationContext中时会应用这一步);
-
ApplicationEventPublisherAware接口的setApplicationEventPublisher方法。(只有运行在一个ApplicationContext中时会应用这一步);
-
MessageSourceAware接口的setMessageSource方法。(只有运行在一个ApplicationContext中时会应用这一步);
-
ApplicationContextAware接口的setApplicationContext方法。(只有运行在一个ApplicationContext中时会应用这一步);
-
ServletContextAware接口的setServletContext方法。(只有运行在一个Web类型的ApplicationContext中时会应用这一步);
-
所有注册的BeanPostProcessor的postProcessBeforeInitialization方法;
-
InitializingBean接口的afterPropertiesSet方法;
-
自定义init-method方法;
-
所有注册的BeanPostProcessor的postProcessAfterInitialization方法。
当BeanFactory关闭的时候会经过如下生命周期:
-
所有注册的DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法;
-
DisposableBean接口的destroy方法;
-
自定义destroy-method方法。
介绍完BeanFactory初始化Bean的过程后,我们来看看这个接口中的方法(这里有个需要注意的点,SpringFramework中获取Bean的时候,如果参数名是name,通常既可以是Bean的名称又可以是Bean的别名,如果参数名是beanName,则只能是Bean的名称):
-
Object getBean(String name) throws BeansException:根据Bean的名字在BeanFactory中查找对应的Bean定义,返回找到的示例。返回的实例可能是单例也可能是Prototype实例。如果传入的name是别名,会翻译成对应的标准Bean名称(下同,不再赘述)。
-
<T> T getBean(String name, Class<T> requiredType) throws BeansException:提供类型检查并返回对应类型的Bean实例。返回的实例可能是Singleton也可能是Prototype实例。
-
Object getBean(String name, Object... args) throws BeansException:根据传入的参数查找有匹配构造函数的Bean定义。只能用于返回Prototype实例。如果不是Prototype会抛出异常BeanDefinitionStoreException。
-
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType):根据传入的类型返回对应的ObjectProvider。ObjectProvider是ObjectFactory的子类,他们可以用于在程序中注入Scope生命周期比当前短的Bean。如在一个Singleton的实例中注入一个Scope是request的Bean。
-
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType):ResolvableType封装了Java中的Type类型,提供访问父类、接口、泛型等功能。
-
boolean containsBean(String name):根据名称在BeanFactory中查找对应的Bean,找到返回true否则返回false。查找包含Bean定义是抽象、懒加载,且包含全部范围,因此即使该方法返回true,也不意味着getBean方法一定能返回正确的实例。
-
boolean isSingleton(String name) throws NoSuchBeanDefinitionException:根据传入的名字返回对应的Bean是否是一个共享实例。
-
boolean isPrototype(String name) throws NoSuchBeanDefinitionException:根据传入的名字返回对应的Bean是否是一个独立实例。
-
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException:根据传入的名字判断BeanFactory中对应的Bean定义类型是否匹配指定的类型。
-
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException:同上。
-
Class<?> getType(String name) throws NoSuchBeanDefinitionException:返回名称所对应的Bean的类型,如果无法确定类型则返回null。如果传入的是一个FactoryBean,则返回FactoryBean创建的类型,即FactoryBean.getObjectType()的返回值。该方法为了确定类型,会初始化之前未初始化过的FactoryBean。
-
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException:同上。第二参数决定是否初始化之前未初始化过的FactoryBean。
-
String[] getAliases(String name):如果存在,则根据名字返回Bean的别名,如果传入的是一个别名,则数组的第一个元素是Bean的标准名称。
5.2 ListableBeanFactory
继承自BeanFactory。该接口提供内部管理的Bean的遍历功能,不需要客户端根据指定的name进行查找。该接口中的方法只关注本层管理的Bean定义,不会去父层查找,会忽略其它方式注册过的Singleton范围的Bean,除了getBeanNamesForType和getBeansOfType方法。该接口中的方法不应频繁调用,执行速度可能会较慢。内部方法如下:
-
boolean containsBeanDefinition(String beanName):检查该BeanFactory中是否存在指定的bean定义。
-
int getBeanDefinitionCount():返回该BeanFactory中的Bean定义数量。
-
String[] getBeanDefinitionNames():返回该BeanFactory中的所有Bean名称。
-
String[] getBeanNamesForType(ResolvableType type):返回匹配指定类型的bean名称(匹配包含子类)。不会检查内部嵌套声明的Bean的类型。等同于getBeanNamesForType(type, true, true)。
-
String[] getBeanNamesForType(@Nullable Class<?> type):同上。
-
String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit):同上。第二参数表示是否包括prototype和有范围的Bean。第三参数表示否是允许初始化懒初始化的Bean和FactoryBean创建的对象。
-
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit):同上。
-
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException:返回匹配指定类型的Bean。(匹配包括子类)
-
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException:同上。
-
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType):返回被指定注解所注释的Bean实例。
-
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException:回被指定注解所注释的Bean实例。
-
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException:查找Bean上的指定注解,如果未找到继续在接口和父接口中查找。
5.3 HierarchicalBeanFactory
继承自BeanFactory。该接口的BeanFactory会处在一个分层体系中。在查找Bean的时候,先找本层BeanFactory,如果没有找到会继续找父BeanFactory中的。方法如下:
-
BeanFactory getParentBeanFactory():返回父BeanFactory。设置父BeanFactory在ConfigurableBeanFactory接口中。
-
boolean containsLocalBean(String name):只在本层查找是否存在指定名称的Bean。
5.4 AutowireCapableBeanFactory
继承自BeanFactory。这个接口可以向Spring管理之外的对象注入Bean。这里暂时先略过,后面说ConfigurableListableBeanFactory时重点说。
5.5 SingletonBeanRegistry
该接口为Singleton范围的bean提供注册能力。具体方法如下:
-
void registerSingleton(String beanName, Object singletonObject):向注册表中注册一个已存在的对象实例,并表示该Bean是一个Singleton。由于注册时实例已经初始化完成,因此不会调用Spring的初始化回调方法和销毁回调方法。
-
Object getSingleton(String beanName):返回beanName对应的Bean,返回的Bean一定是初始化完成的,并且该方法不处理别名。
-
boolean containsSingleton(String beanName):返回是否存在一个已经实例化好的且名称为指定名称的bean。
-
String[] getSingletonNames():返回所有实例化好的Singleton范围的Bean的名字。
-
int getSingletonCount():返回所有实例化好的单例Bean的个数。
-
Object getSingletonMutex():这个方法暂时不知道是干什么的,后面遇到再说。
5.6 ConfigurableBeanFactory
如上图所示,ConfigurableBeanFactory接口继承了SingletonBeanRegistry和HierarchicalBeanFactory。因此具有注册Singleton范围的Bean和拥有分层关系的能力。该接口提供对BeanFactory的配置能力,通常业务代码不应使用该接口的能力。接口中定义了singleton和prototype的范围常量。接口中的方法有些多,和ConfigurableApplicationContext类似,接口中开始出现设值方法,具体如下:
-
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException:设置父BeanFactory,设置后就不能改变。
-
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader):设置Bean的类加载器,默认是线程上下文的类加载器。该类加载器只对尚未被解析的Bean定义生效。
-
ClassLoader getBeanClassLoader():获取Bean的类加载器。
-
void setTempClassLoader(@Nullable ClassLoader tempClassLoader):设置一个临时的类加载器,默认是null。通常在装载时织入时,为了尽可能晚的加载Bean的类会设置这个类加载器。一旦BeanFactory完成启动,该类加载器会被移除。
-
ClassLoader getTempClassLoader():获取临时类加载器。
-
void setCacheBeanMetadata(boolean cacheBeanMetadata):设置是否缓存Bean的元数据。默认是true。设置为false时可以对bean定义做热重载。
-
boolean isCacheBeanMetadata():是否开启元数据缓存。
-
void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver):设置Bean定义中表达式的解析器,默认为null。由子类选择实现,如EL表达式。
-
BeanExpressionResolver getBeanExpressionResolver():获取表达式解析器。
-
void setConversionService(@Nullable ConversionService conversionService):设置一个ConversionService用来对Bean属性值进行转换。转换的另一个方法是使用Java自带的PropertyEditor。
-
ConversionService getConversionService():返回设置的ConversionService。
-
void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar):设置一个PropertyEditorRegistrar应用于所有Bean的创建过程,该registrar会创建一个PropertyEditor实例,并且将它注册到注册表中,因此通常比registerCustomEditor方法便捷。
-
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass):为指定的类型注册一个PropertyEditor。
-
void copyRegisteredEditorsTo(PropertyEditorRegistry registry):使用该BeanFactory中已经配置好的PropertyEditor初始化指定的PropertyEditorRegistry。
-
void setTypeConverter(TypeConverter typeConverter):设置一个TypeConverter来为Bean属性进行类型转换。该TypeConverter会覆盖PropertyEditor机制。
-
TypeConverter getTypeConverter():返回设置的TypeConverter。
-
void addEmbeddedValueResolver(StringValueResolver valueResolver):为内嵌值设置字符串解析器。内嵌值的例子比如注解的属性等。
-
boolean hasEmbeddedValueResolver():返回该BeanFactory是否设置了内嵌值字符串转换器。
-
String resolveEmbeddedValue(String value):解析指定的内嵌值。
-
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor):添加一个BeanPostProcessor,用于在每个Bean的创建时可以进行额外的处理。添加多个会默认根据添加顺序调用,可使用Ordered接口指定顺序。
-
int getBeanPostProcessorCount():返回当前注册的BeanPostProcessor的个数。
-
void registerScope(String scopeName, Scope scope):注册一个Scope。
-
String[] getRegisteredScopeNames():返回注册的Scope,不包含内置的。
-
Scope getRegisteredScope(String scopeName):根据名称返回注册的Scope,不包含内置的。
-
AccessControlContext getAccessControlContext():返回当前BeanFactory的安全访问上下文。
-
void copyConfigurationFrom(ConfigurableBeanFactory otherFactory):从一个指定的BeanFactory中拷贝配置,不包含bean定义。
-
void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException:为beanName注册一个别名。
-
void resolveAliases(StringValueResolver valueResolver):设置一个字符串解析器来对别名进行解析,如占位符。
-
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException:如果Bean由父,则返回合并后的Bean定义。
-
boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException:判断给定的名字是否是一个FactoryBean。
-
void setCurrentlyInCreation(String beanName, boolean inCreation):为Bean设置正在创建中的状态,仅应该容器内使用。
-
boolean isCurrentlyInCreation(String beanName):判断Bean是否正在创建。
-
void registerDependentBean(String beanName, String dependentBeanName):为指定bean注册一个依赖bean,当指定的bean被销毁之前,依赖bean会被先销毁。
-
String[] getDependentBeans(String beanName):返回bean的依赖bean名称。
-
String[] getDependenciesForBean(String beanName):返回指定bean依赖的bean名称。
-
void destroyBean(String beanName, Object beanInstance):销毁Bean实例,通常是Prototype的Bean。
-
void destroyScopedBean(String beanName):销毁Bean实例,改Bean是一个有范围的Bean。
-
void destroySingletons():销毁该BeanFactory中的所有Singleton范围的Bean。
5.7 ConfigurableListableBeanFactory
从上图可以看出,ConfigurableListableBeanFactory继承了ConfigurableBeanFactory、AutowireCapableBeanFactory和ListableBeanFactory。其中ListableBeanFactory和ConfigurableListableBeanFactory上面已经分析过了。AutowireCapableBeanFactory提供对一个Java对象进行自动装配的能力,不应在业务代码中使用。
AutowireCapableBeanFactory方法如下:
-
<T> T createBean(Class<T> beanClass) throws BeansException:创建一个Bean实例。不会应用byName或byType的自动装配,会应用注解注入。该方法会调用所有注册的BeanPostProcessor中的相关方法,这在编写框架和类库中非常有用。同时也会调用相关的初始化方法。
-
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException:创建一个Bean实例,第二参数指定自动装配使用byName还是byType。第三参数表示是否执行依赖检查。
-
void autowireBean(Object existingBean) throws BeansException:自动装配一个已存在的Bean实例。不会应用BeanPostProcessor。
-
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException:另外两个参数的含义和三参数的create方法一样。
-
Object configureBean(Object existingBean, String beanName) throws BeansException:使用一个已存在的对象配置一个Bean
-
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException:为已存在的Bean实例自动装配属性。不会应用BeanPostProcessor。
-
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException:这个方法不会对属性进行自动装配,而是显示的指定。也不会应用标准的BeanPostProcessors回调方法。
-
Object initializeBean(Object existingBean, String beanName) throws BeansException:初始化Bean。会调用所有注册的BeanPostProcessor中的相关方法。
-
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException:在已存在的Bean实例上,调用所有BeanPostProcessor的postProcessBeforeInitialization方法。
-
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException:在已存在的Bean实例上,调用所有BeanPostProcessor的postProcessorsAfterInitialization方法。
-
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException:解析唯一匹配给定类型的Bean实例。
-
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException:解析给定名称的Bean实例。
-
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException:解析依赖。
-
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException:解析依赖并应用类型转换和自动装配。
ConfigurableListableBeanFactory中的方法:
-
void ignoreDependencyType(Class<?> type):在自动装配时忽略指定的类型。默认是null。
-
void ignoreDependencyInterface(Class<?> ifc):在自动装配时忽略指定的接口。默认只有BeanFactoryAware被忽略。
-
void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue):当一个类型有多个实现类,且注入的是这个类型时,可以使用这个方法来为该接口设置默认的注入值。
-
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException:判断制定的Bean是否是一个依赖的候选Bean,用于注入到别的Bean中。
-
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException:返回指定的Bean定义,并可以访问其属性和构造参数。
-
Iterator<String> getBeanNamesIterator():返回所有Bean名称的视图,包括手动注册的Singleton的Bean。
-
void clearMetadataCache():清空元数据缓存。
-
void freezeConfiguration():冻结所有Bean定义,不允许再被修改。
-
boolean isConfigurationFrozen():Bean定义是否已经被冻结。
-
void preInstantiateSingletons() throws BeansException:确保所有非延迟初始化的Singleton的Bean被初始化。该方法通常在BeanFactory完成初始化之前被调用。
6. 小结二
到此为止,我们可以看出。最核心的接口是BeanFactory。ApplicationContext主要继承了BeanFactory接口的HierarchicalBeanFactory和ListableBeanFactory子类,因此ApplicationContext拥有检索Bean、遍历Bean和构建层次化Bean结构的能力。ConfigurableApplicationContext继承了ApplicationContext、Lifecycle和Closeable,额外提供生命周期相关的能力和设置上下文属性的能力。而ConfigurableBeanFactory,继承了SingletonBeanRegistry和AutowireCapableBeanFactory,提供针对BeanFactory的设值能力,并且提供设置Bean初始化时的一些额外配置,如类型转换等。ConfigurableListableBeanFactory继承自ConfigurableBeanFactory、AutowireCapableBeanFactory和ListableBeanFactory,提供了依赖管理、自动装配和遍历的能力。
可以看出,ApplicationContext继承BeanFactory主要是提供检索能力,那么是什么把ApplicationContext和BeanFactory的子接口联系到一起呢。这就是ApplicationContext的实现类,上面也提到过,在实现类中会有BeanFactory子类的引用,任何和Bean相关的创建和检索等都会委托给这个引用来处理。
7. ApplicationContext实现类和DefaultListableBeanFactory
我们先来看一下ApplicationContext的实现类。注意:ApplicationContext的实现类非常多,这里只列出SpringFramework的context包中的典型实现类。
可以看出,自抽象类AbstractApplicationContext之下分为了GenericApplicationContext和AbstractRefreshableApplicationContext,两者内部都有一个DefaultListableBeanFactory对象,后者的每个子类上下文只能从一种格式的配置文件中加载bean定义文件,如xml,refresh方法可以执行多次,每次都会创建一个新的内部beanFactory。前者可以从多种格式的配置中读取bean定义,读取后只能调用一次refresh来解析这些bean定义。我们熟悉的ClassPathXmlApplicationContext是AbstractRefreshableApplicationContext体系下的一个子类。而我们开篇使用的AnnotationConfigApplicationContext则是GenericApplicationContext的子类。
上一段中提到的DefaultListableBeanFactory则是目前ConfigurableListableBeanFactory接口的唯一实现类。类图如下:
上图中可以看出,DefaultListableBeanFactory实现了所有BeanFactory相关接口,拥有所有能力。
8. 总结
通过上面的分析,我们可以看出。在SpringFramework中最顶层的核心接口是BeanFactory。ApplicationContext继承了部分上层的BeanFactory子接口,主要用于Bean的检索,而自身则主要提供上下文生命周期、上下文属性、资源管理、国际化、事件管理等功能。ApplicationContext的具体实现类中都会持有DefaultListableBeanFactory类的实例,该实例实现了所有BeanFactory及其子接口的能力,ApplicationContext将所有Bean的创建和检索等操作都委托给这个实例进行实际处理。因此我们通常所说的SpringFramework容器就指的是BeanFactory接口的实现类,实际上就是DefaultListableBeanFactory。
简而言之,最顶层的BeanFactory代表了Bean的容器,ApplicationContext将Bean的创建和检索等功能委托给BeanFactory来处理。对应用程序而言,由于ApplicationContext继承了BeanFactory,因此将BeanFactory放置在了后端,这样对于开发人员来说,SpringFramework的入口只需要关注ApplicationContext就可以了。
而在继承恭喜中我们也可以看出,顶层的BeanFactory只有取值方法,下面每一层子类都提供一种能力,比如第一层子类提供遍历、分层关系等能力(如ListableBeanFactory和HierarchicalBeanFactory),第二层提供配置能力,出现设值方法(如ConfigurableBeanFactory和ConfigurableApplicationContext),接着就是实现类,由抽象到具体。这种接口和抽象类的设计方式,是值得学习的。
由于ConfigurableBeanFactory和ApplicationContext都支持分层,因此,在一个代码工程中可能会出现多个上下文环境,这些上下文可能是并列关系也可能是父子关系,每个上下文中都会有一个DefaultListableBeanFactory作为容器,而个容器也可能具有父容器。这就为模块化提供了便利。
在SpringFramework的包结构中,BeanFactory位于spring-beans模块中的org.springframework.beans.factory包下。ApplicationContext位于spring-context模块下的org.springframework.context和org.springframework.context.support包下。
本次我们主要介绍了SpringFramework中的ApplicationContext和BeanFactory的继承关系及各个子接口的能力。今天的介绍将会作为之后其它部分介绍的基础,有助于更加系统的分析源码、理解源码。下次我们会从启动开始真正深入到SpringFramework的源码逻辑中。
下面附上本次介绍的完整类图(使用的是开源版的StarUML画的图,导出的图片有水印):
更多内容请关注我的公众号: