BeanDefinition是bean在spring中的描述,有了BeanDefinition我们就可以创建Bean,BeanDefinition是Bean在spring中的定义形态
scope(@Scope)
lazy-init(@Lazy)
:决定Bean实例是否延迟加载primary(@Primary)
:设置为true 的bean会是优先的实现类factory-bean
和factory-method
(@Configuration
和@Bean
)BeanFactory
,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。
在Spring中,BeanFactory
是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
所有ioc容器都需要实现该接口。
public interface BeanFactory {
//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
//如果需要得到工厂本身,需要转义
String FACTORY_BEAN_PREFIX = "&";
//根据bean的名字,获取在IOC容器中得到bean实例
Object getBean(String name) throws BeansException;
//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
//提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//根据bean名字得到bean实例,并同时判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
//得到bean实例的Class类型
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}
一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。
public interface FactoryBean<T> {
//从工厂中获取bean
@Nullable
T getObject() throws Exception;
//获取Bean工厂创建的对象的类型
@Nullable
Class<?> getObjectType();
//Bean工厂创建的对象是否是单例模式
default boolean isSingleton() {
return true;
}
}
从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上&
符号。
getObject('name')
返回工厂中的实例getObject('&name')
返回工厂本身的实例通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。
最大的特点就是可以列出工厂可以生产的所有实例及其属性。
这个工厂接口非常简单,实现了Bean工厂的分层。这个工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层。
第一个方法返回本Bean工厂的父工厂。这个方法实现了工厂的分层。
第二个方法判断本地工厂是否包含这个Bean(忽略其他所有父工厂)。这也是分层思想的体现。
这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配Bean、执行前、后处理器等。
继承自HierarchicalBeanFactory
和 SingletonBeanRegistry
这两个接口
ConfigurableBeanFactory
定义BeanFactory的配置.ConfigurableBeanFactory
中定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor
,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory
,bean如何销毁.
spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说,DefaultListableBeanFactory 是整个spring ioc的始祖
默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于bean definition对象,是一个成熟的bean factroy。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver{...}
EnvironmentCapable
获取环境ListableBeanFactory
以列表的方式管理BeanHierarchicalBeanFactory
多层级的容器MessageSource
解决message的能力,即支持国际化ApplicationEventPublisher
让容器拥有发布应用上下文事件的功能,包括容器的启动事件、关闭事件等ResourcePatternResolver
加载资源文件ApplicationContext
中没有set方法,只有get读取方法。
FileSystemXmlApplicationContext
从文件系统下的一个或多个XML 配置文件加载上下文定义。ClassPathXMLApplicationContext
从类路径下的一个或多个XML 配置文件加载上下文定义。XmlWebApplicationContext
从Web 应用下的一个或多个XML 配置文件中加载上下文定义。AnnotationConfigServletWebServerApplicationContext
AnnotationConfigReactiveWebServerApplicationContext
AnnotationConfigApplicationContext
ConfigurableApplicationContext
直接继承了 ApplicationContext
, Lifecycle
, Closeable
接口
Lifecycle
接口则是负责对 context
的生命周期进行管理,提供了 start()
和 stop()
以及 isRunning()
方法。
Closeable
接口是JDK提供的接口,用于关闭组件,释放资源。
所以 ConfigurableApplicationContext
接口的作用就是设置上下文 ID,设置父应用上下文,添加监听器,刷新容器refresh()
,关闭容器close()
,判断是否活跃isActive()
等方法。其实简单看一下 ApplicationContext
接口就会发现里面之后get方法,没有set方法,所以子接口就提供了set方法。
AbstractApplicationContext
是Spring应用上下文中最重要的一个类,这个抽象类中提供了几乎ApplicationContext
的所有操作。主要有容器工厂的处理,事件的发送广播,监听器添加,容器初始化操作refresh方法,然后就是bean的生成获取方法接口等。
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
它是spring访问资源最基本的接口。实际访问的时候直接用Resource接口就可以,不必使用其子类。其实经常用到的(resource的真正目的)方法是public InputStream getInputStream()。
主要实现了对资源文件的编码处理。
? 匹配任何单字符
* 匹配0或者任意数量的字符
** 匹配0或者更多的目录
例如:
/app/*.x 匹配(Matches)所有在app路径下的.x文件
/app/p?ttern 匹配(Matches) /app/pattern 和 /app/pXttern,但是不包括/app/pttern
/**/example 匹配(Matches) /app/example, /app/foo/example, 和 /example
/app/**/dir/file. 匹配(Matches) /app/dir/file.jsp, > /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf, 和 /app/dir/file.java
/**/*.jsp 匹配(Matches)任何的.jsp 文件
该接口中只定义了一个用于获取Resource的getResource(String location)方法。
DefaultResourceLoader
在获取Resource
时采用的是这样的策略:首先判断指定的location是否含有“classpath:”
前缀,如果有则把location去掉“classpath:”
前缀返回对应的ClassPathResource
;否则就把它当做一个URL来处理,封装成一个UrlResource
进行返回;如果当成URL处理也失败的话就把location
对应的资源当成是一个ClassPathResource
进行返回。
BeanDefinitionReader ,该接口的作用就是加载 Bean。
在 Spring 中,Bean 一般来说都在配置文件中定义。而在配置的路径由在 web.xml 中定义。所以加载 Bean 的步骤大致就是:
Spring配置文件的解析是通过BeanDefinitionReader来实现的,其实了解BeanDefinitionReader实现的机制就会发现,其只是将ApplicationContext的.xml配置文件解析成Document对象,真正对xml中元素解析的类是在BeanDefinitionDocumentReader的实现类中来完成的
BeanDefinitionDocumentReader
提供的方法:
public interface BeanDefinitionDocumentReader {
void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
throws BeanDefinitionStoreException;
}
在DefaultBeanDefinitionDocumentReader
的registerBeanDefinitions
方法中开始对Document
进行解析。
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
BeanDefinitionDocumentReader
中也没有对xml中的bean元素进行处理操作,其真正的处理操作是在BeanDefinitionParserDelegate
中进行处理的
用于BeanDefinition的注册
FileSystemXmlApplicationContext
读取xml配置文件路径refresh()
方法初始化容器
refresh()
中的obtainFreshBeanFactory()
解析配置