调用时序图:
容器实现的实现代码庞杂,完全抽象出来其实仅仅三个步骤:资源定位、资源加载、资源注册;
DefaultListableBeanFactory 类是核心容器,且主要实现注册的核心逻辑,并通过上下文传递的方式在最后实现注册;
AbstractRefreshableApplicationContext 及其子类则是为了实现良好的扩展性,对资源定位进行的封装,针对注解、xml、其他配置等提供不同的资源定位实现;
在加载过程中主要采用的策略模式:NamespaceHandler 和 BeanDefinitionParser + BeanDefaultReader 实现资源加载
体系设计1,BeanFactory:Bean工厂 为IOC容器管理对象间依赖关系提供基础服务。
顶层接口:BeanFactory,定义IOC容器基本功能规范,在spring中万物皆对象,万物皆工厂;因此BeanFactory与FactoryBean一样为一切类的初始,(其后定义Bean集合和Bean之间关系的接口有: ListableBeanFactory-可列表Bean、HierarchicalBeanFactory -继承关系Bean、AutowireCapableBeanFactory - 自动装配规则Bean;)
第二层行为类接口:ResourceLoader - 资源加载、AliasRegistry - BeanDefinition的注册、 NamespaceHandler - 命名空间处理器、 BeanDefinitionParser - BeanDefinition解析器 、
其他外部扩展接口:BeanNameAware - 提供的外部扩展接口、InitializingBean- 提供的外部扩展接口
第三层具体实现: 默认实现:DefaultListableBeanFactory,实现了所有接口;
具体的IOC容器实现:XmlBeanFactory,ClasspathXmlApplicationContext 等;
多层次接口实现原因: 区分操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。
类图中有趣的设计模式点:
//ApplicationContext parent 实现类似双亲委派模式
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {
private ApplicationContext parent;
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors;
private Thread shutdownHook;
private ResourcePatternResolver resourcePatternResolver;
private MessageSource messageSource;
private ApplicationEventMulticaster applicationEventMulticaster;
private final Set<ApplicationListener<?>> applicationListeners;
private Set<ApplicationEvent> earlyApplicationEvents;
public AbstractApplicationContext() {
this.resourcePatternResolver = this.getResourcePatternResolver();
}
public AbstractApplicationContext(ApplicationContext parent) {
this();
this.setParent(parent);
}
}
//AbstractBeanFactory: parentBeanFactory 实现子类与父类关系的维护
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
private BeanFactory parentBeanFactory;
public AbstractBeanFactory() {
}
public AbstractBeanFactory(BeanFactory parentBeanFactory) {
this.parentBeanFactory = parentBeanFactory;
}
}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
private Boolean allowBeanDefinitionOverriding;
private Boolean allowCircularReferences;
//静态代理模式: DefaultListableBeanFactory 作为实现核心,
// 里面存储所有的容器核心参数,是实现BeanDefinition注册的真正实现
private DefaultListableBeanFactory beanFactory;
// 这里为何新建一个 beanFactoryMonitor 作为加锁对象呢???
private final Object beanFactoryMonitor = new Object();
protected final void refreshBeanFactory() throws BeansException {
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//加载BeanDefinition的实现方法
this.loadBeanDefinitions(beanFactory);
//加锁为何要如此实现呢?
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
}
DefaultListableBeanFactory核心容器主要参数
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private static Class javaxInjectProviderClass = null;
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
private String serializationId;
private boolean allowBeanDefinitionOverriding = true;
private boolean allowEagerClassLoading = true;
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
private final Map<Class, Object> resolvableDependencies = new HashMap();
//spring核心IOC容器
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap();
private final List<String> beanDefinitionNames = new ArrayList();
private boolean configurationFrozen = false;
private String[] frozenBeanDefinitionNames;
static {
ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
try {
javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
} catch (ClassNotFoundException var1) {
}
serializableFactories = new ConcurrentHashMap();
}
}
ClassPathXmlApplicationContext启动类
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
//实现自己特有的方式的资源加载
private Resource[] configResources;
//父类通过子类重写该方法实现获取子类资源信息
@Override
protected Resource[] getConfigResources() {
return null;
}
}
体系设计2,BeanDefinition: 定义描述bean对象及其相互关系;及实现BeanDefinition初始化接口
BeanDefinition来实现对Bean对象的描述,解析过程非常复杂,功能主要被XmlBeanDefinitionReader实现;
主要实现 XmlBeanDefinitionReader 是类 AbstractXmlApplicationContext中new进行创建,并调用加载注册;
整个调用过程的: XmlBeanDefinitionReader - NamespaceHandlerResolver - NamespaceHandler - BeanDefintionParser - BeanDefinitionRegistry 实现解析和注册()
ApplicationContext
读取文档上下文对象:
ReaderContext{
Resource 解析资源
ProblemReporter
ReaderEventListener 时间监听
SourceExtractor
}
XmlReaderContext extends ReaderContext {
XmlBeanDefinitionReader{
BeanDefinitionRegistry bena注册器
loadBeanDefinitions(Resource... resources) -- 将resource地址转换为XML的Documnet
}
NamespaceHandlerResolver 解析handler
registerWithGeneratedName(BeanDefinition beanDefinition) --
}
XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.namespaceHandlerResolver)
解析上下文对象
new ParserContext(this.readerContext, this, containingBd){
XmlReaderContext
BeanDefinitionParserDelegate
BeanDefinition
}
策略对象1: NamespaceHandler = XmlReaderContext.getNamespaceHandlerResolver().resolve(namespaceUri)
NamespaceHandler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
策略对象2: BeanDefinitionParser = (BeanDefinitionParser)this.parsers.get(ParserContext.getDelegate().getLocalName(element))
最终完成注册:
BeanDefinitionRegistry实现注册写入数据
3、IOC容器初始化过程:初始化过程包含 Resource定位、载入、注册三个过程;
ApplicationContext 是我们最熟悉的上下文容器,其实现包括 XmlWebApplicationContext、ClasspathXmlApplicationContext、 FileSystemXmlApplicationContext; 其采用类加载器的设计方式,允许上下文嵌套,当Bean查找在当前上下文找不到,则取父上下文查找,逐级向上。
【实现原因】:实现共享的Bean定义环境;
①源码实现: XmlBeanFactory
// 根据Xml 配置文件创建Resource 资源对象,该对象中包含了BeanDefinition 的信息
ClassPathResource resource = new ClassPathResource("application-context.xml");
// 创建DefaultListableBeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建XmlBeanDefinitionReader 读取器,用于载入BeanDefinition。
// 之所以需要BeanFactory 作为参数,是因为会将读取的信息回调配置给factory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// XmlBeanDefinitionReader 执行载入BeanDefinition 的方法,最后会完成Bean 的载入和注册。
// 完成后Bean 就成功的放置到IOC 容器当中,以后我们就可以从中取得Bean 来使用
reader.loadBeanDefinitions(resource);
②源码实现:FileSystemXmlApplicationContext
构造函数调用:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent); //调用1:默认实现 AbstractApplicationContext,为容器设置Bean资源加载器
setConfigLocations(configLocations); //调用2:设置Bean定义资源文件的定位路径。
if (refresh) {
refresh(); //调用3:刷新容器, 载入Bean定义;
}
}
//调用1、父类初始化实现
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
//静态初始化块,在整个容器创建过程中只执行一次
static {
//为了避免应用程序在Weblogic8.1 关闭时出现类加载异常加载问题,加载IOC 容
//器关闭事件(ContextClosedEvent)类
ContextClosedEvent.class.getName();
}
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent); //设置父类容器(类加载器模式-统一的容器环境)
}
//获取一个Spring Source 的加载器用于读入Spring Bean 定义资源文件
protected ResourcePatternResolver getResourcePatternResolver() {
//AbstractApplicationContext 继承DefaultResourceLoader,因此也是一个资源加载器
//Spring 资源加载器,其getResource(String location)方法用于载入资源
return new PathMatchingResourcePatternResolver(this);
}
...
}
//调用1-1
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
//设置Spring 的资源加载器
this.resourceLoader = resourceLoader;
}
//调用2:处理单个资源文件路径为一个字符串的情况
public void setConfigLocation(String location) {
//String CONFIG_LOCATION_DELIMITERS = ",; /t/n";
//即多个资源文件路径之间用” ,; \t\n”分隔,解析成数组形式
setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
}
//解析Bean 定义资源文件的路径,处理多个资源文件字符串数组
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
// resolvePath 为同一个类中将字符串解析为路径的方法
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}else {
this.configLocations = null;
}
}
//调用3 容器存在则销毁和关闭,并新建IOC容器;AbstractApplicationContext 类实现
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
//调用3-1、告诉子类启动refreshBeanFactory()方法,Bean 定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//为BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定特殊的BeanPost 事件处理器
postProcessBeanFactory(beanFactory);
//调用所有注册的BeanFactoryPostProcessor 的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//为BeanFactory 注册BeanPost 事件处理器.
//BeanPostProcessor 是Bean 后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关.
initMessageSource();
//初始化容器事件传播器.
initApplicationEventMulticaster();
//调用子类的某些特殊Bean 初始化方法
onRefresh();
//为事件传播器注册事件监听器.
registerListeners();
//初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);
}
//销毁已创建的Bean
destroyBeans();
//取消refresh 操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
//调用3-1、告诉子类启动refreshBeanFactory()方法
// AbstractApplicationContext # obtainFreshBeanFactory() 中调用子类实现 refreshBeanFactory
// 真正调用 AbstractRefreshableApplicationContext 的实现;
protected final void refreshBeanFactory() throws BeansException {
//如果已经有容器,销毁容器中的bean,关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建IOC 容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对IOC 容器进行定制化,如设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
//调用3-1-1,载入Bean 定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions 方法,具体的实现调用子类容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(),ex);
}
}
//调用3-1-1、载入Bean 定义的方法,主要这里又使用了一个委派模式,
//在当前类中只定义了抽象的loadBeanDefinitions方法,具体由子类AbstractXmlApplicationContext容器实现;
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
...
//实现父类抽象的载入Bean 定义方法
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建XmlBeanDefinitionReader,即创建Bean 读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean 定义资源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//为Bean 读取器设置Spring 资源加载器,AbstractXmlApplicationContext 的
//祖先父类AbstractApplicationContext 继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
//为Bean 读取器设置SAX xml 解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//当Bean 读取器读取Bean 定义的Xml 资源文件时,启用Xml 的校验机制
initBeanDefinitionReader(beanDefinitionReader);
//※Bean 读取器真正实现加载的方法
loadBeanDefinitions(beanDefinitionReader);
}
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
//Xml Bean 读取器加载Bean 定义资源
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//获取Bean 定义资源的定位
Resource[] configResources = getConfigResources();
if (configResources != null) {
//Xml Bean 读取器调用其父类AbstractBeanDefinitionReader 读取定位的Bean 定义资源
reader.loadBeanDefinitions(configResources);
}
// ※如果子类中获取的Bean 定义资源定位为空,则获取 FileSystemXmlApplicationContext
// 构造方法中setConfigLocations 方法设置的资源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//调用3-1-1-1、Xml Bean 读取器调用其父类AbstractBeanDefinitionReader 读取定位
//的Bean 定义资源
reader.loadBeanDefinitions(configLocations);
}
}
//这里又使用了一个委托模式,调用子类的获取Bean 定义资源定位的方法
//该方法在ClassPathXmlApplicationContext 中进行实现,对于我们
//举例分析源码的FileSystemXmlApplicationContext 没有使用该方法
@Nullable
protected Resource[] getConfigResources() {
return null;
}
}
//调用3-1-1-1、读取器调用其父类AbstractBeanDefinitionReader 读取定位的Bean定义资源
//重载方法,调用下面的loadBeanDefinitions(String, Set<Resource>);方法
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取在IOC 容器初始化过程中设置的资源加载器
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
//调用3-1-1-1-1、将指定位置的Bean 定义资源文件解析为Spring IOC 容器封装的资源
//加载多个指定位置的Bean 定义资源文件
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
//调用3-1-1-1-2,资源加载要获取的资源:委派调用其子类XmlBeanDefinitionReader的loadBeanDefinitions方法,实现加载功能,实际实现为DefaultResourceLoader # getSource()
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}catch (IOException ex) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}else {
// Can only load single resources by absolute URL.
//将指定位置的Bean 定义资源文件解析为Spring IOC 容器封装的资源
//加载单个指定位置的Bean 定义资源文件
Resource resource = resourceLoader.getResource(location);
//委派调用其子类XmlBeanDefinitionReader 的方法,实现加载功能
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
//重载方法,调用loadBeanDefinitions(String);
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
//调用3-1-1-1-1、实际实现为DefaultResourceLoader # getSource()获取Resource 的具体实现方法
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
for (ProtocolResolver protocolResolver : this.protocolResolvers) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
//如果是类路径的方式,那需要使用ClassPathResource 来得到bean 文件的资源对象
if (location.startsWith("/")) {
return getResourceByPath(location);
}else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}else {
try {
// 如果是URL 方式,使用UrlResource 作为bean 文件的资源对象
URL url = new URL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}catch (MalformedURLException ex) {
//如果既不是classpath 标识,又不是URL 标识的Resource 定位,则调用
//容器本身的getResourceByPath 方法获取Resource
return getResourceByPath(location);
}
}
}
//调用3-1-1-1-2,委派调用其子类XmlBeanDefinitionReader的loadBeanDefinitions方法实现
//功能2:加载BeanDefinition
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//将读入的XML 资源进行特殊编码处理
return loadBeanDefinitions(new EncodedResource(resource));
}
//这里是载入XML 形式Bean 定义资源文件方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
...
try {
//将资源文件转为InputStream 的IO 流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//从InputStream 中得到XML 的解析源
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//这里是具体的读取过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}finally {
//关闭从Resource 中得到的IO 流
inputStream.close();
}
}
...
}
//从特定XML 文件中实际载入Bean 定义资源的方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//调用1,3-1-1-1-2-1、将XML 文件转换为DOM 对象,解析过程由documentLoader 实现,这里调用的JAVAEE标准的JAXP标准,解析意义不大,跳过;
Document doc = doLoadDocument(inputSource, resource);
//调用2,3-1-1-1-2-2、这里是启动对Bean 定义解析的详细过程,该解析过程会用到Spring 的Bean 配置规则;
return registerBeanDefinitions(doc, resource);
}
...
}
//按照Spring 的Bean 语义要求将Bean 定义资源DOCument转换为容器内部数据结构BeanDefinition; 实现类为DefaultBeanDefinitionDocumentReader
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//得到BeanDefinitionDocumentReader 来对xml 格式的BeanDefinition 解析
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获得容器中注册的Bean 数量
int countBefore = getRegistry().getBeanDefinitionCount();
//调用3,3-1-1-1-2-3解析过程入口,
//这里使用了委派模式,BeanDefinitionDocumentReader 只是个接口,
//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader 完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//统计解析的Bean 数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
//※调用3※,3-1-1-1-2-3解析过程入口,DefaultBeanDefinitionDocumentReader # registerBeanDefinitions()
//根据Spring DTD 对Bean 的定义规则解析Bean 定义Document 对象
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
//获得XML 描述符
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
//获得Document 的根元素
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
...
protected void doRegisterBeanDefinitions(Element root) {
//具体的解析过程由BeanDefinitionParserDelegate 实现,
//BeanDefinitionParserDelegate 中定义了Spring Bean 定义XML 文件的各种元素
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//在解析Bean 定义之前,进行自定义的解析,增强解析过程的可扩展性
preProcessXml(root);
//※调用3,3-1-1-1-2-3-1从Document 的根元素开始进行Bean 定义的Document 对象
parseBeanDefinitions(root, this.delegate);
//在解析Bean 定义之后,进行自定义的解析,增加解析过程的可扩展性
postProcessXml(root);
this.delegate = parent;
}
//创建BeanDefinitionParserDelegate,用于完成真正的解析过程
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
//BeanDefinitionParserDelegate 初始化Document 根元素
delegate.initDefaults(root, parentDelegate);
return delegate;
}
//※使用Spring 的Bean 规则从Document 的根元素开始进行Bean 定义的Document 对象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean 定义的Document 对象使用了Spring 默认的XML 命名空间
if (delegate.isDefaultNamespace(root)) {
//获取Bean 定义的Document 对象根元素的所有子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//获得Document 节点是XML 元素节点
if (node instanceof Element) {
Element ele = (Element) node;
//Bean 定义的Document 的元素节点使用的是Spring 默认的XML 命名空间
if (delegate.isDefaultNamespace(ele)) {
//使用Spring 的Bean 规则解析元素节点
parseDefaultElement(ele, delegate);
}else {
//没有使用Spring 默认的XML 命名空间,则使用用户自定义的解//析规则解析元素节点
delegate.parseCustomElement(ele);
}
}
}
}else {
//Document 的根节点没有使用Spring 默认的命名空间,则使用用户自定义的
//解析规则解析Document 根节点
delegate.parseCustomElement(root);
}
}
//使用Spring 的Bean 规则解析Document 元素节点:<Import> <Alias> <Bean>
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素节点是<Import>导入元素,进行导入解析 [可以导入xml配置文件]
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果元素节点是<Alias>别名元素,进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
//按照Spring 的Bean 规则解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//嵌套bean解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
//1、解析标签<Import>导入元素,从给定的导入路径加载其他资源到Spring IOC 容器中
protected void importBeanDefinitionResource(Element ele) {
//获取给定的导入元素的location 属性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
//如果导入元素的location 属性值为空,则没有导入任何资源,直接返回
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
//使用系统变量值解析location 属性值
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<>(4);
//标识给定的导入元素的location 是否是绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}catch (URISyntaxException ex) {
//给定的导入元素的location 不是绝对路径
}
// Absolute or relative?
//给定的导入元素的location 是绝对路径
if (absoluteLocation) {
try {
//使用资源读入器加载给定路径的Bean 定义资源
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}else {
//给定的导入元素的location 是相对路径
try {
int importCount;
//将给定导入元素的location 封装为相对路径资源
Resource relativeResource = getReaderContext().getResource().createRelative(location);
//封装的相对路径资源存在
if (relativeResource.exists()) {
//使用资源读入器加载Bean 定义资源
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
//封装的相对路径资源不存在
else {
//获取Spring IOC 容器资源读入器的基本路径
String baseLocation = getReaderContext().getResource().getURL().toString();
//根据Spring IOC 容器资源读入器的基本路径加载给定导入路径的资源
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location +"]");
}
}catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
//在解析完<Import>元素之后,发送容器导入其他资源处理完成事件
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
//2、解析<Alias>别名元素,为Bean 向Spring IOC 容器注册别名
protected void processAliasRegistration(Element ele) {
//获取<Alias>别名元素中name 的属性值
String name = ele.getAttribute(NAME_ATTRIBUTE);
//获取<Alias>别名元素中alias 的属性值
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
//<alias>别名元素的name 属性值为空
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
//<alias>别名元素的alias 属性值为空
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
//向容器的资源读入器注册别名
getReaderContext().getRegistry().registerAlias(name, alias);
}catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
//在解析完<Alias>元素之后,发送容器别名处理完成事件
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
//※3、解析Bean 定义资源Document 对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder 是对BeanDefinition 的封装,即Bean 定义的封装类
//对Document 对象中<Bean>元素的解析由BeanDefinitionParserDelegate 实现
// 处理<bean>标签的id ,name, alias属性(ele,BeanDefinition);
// 及其他属性解析(ele,beanName,BeanDefinition);类名、父类、单例、描述信息、lookup-Method、replaced-Method、property{ 获取元素名字,获取元素,获取不到则创建,解析其属性- 基本类型,ref、list,set、array、map,properties等类型 }、qualifier;
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//调用3,3-1-1-1-2-3-1、向Spring IOC 容器注册解析得到的Bean 定义,这是Bean 定义向IOC 容器注册的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);
}
//调用3,3-1-1-1-2-3-2、在完成向Spring IOC 容器注册解析得到的Bean 定义之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
//※调用3,3-1-1-1-2-3-1、将解析的BeanDefinitionHold 注册到容器中; BeanDefinitionReaderUtils # registerBeanDefinition()
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//获取解析的BeanDefinition 的名称
String beanName = definitionHolder.getBeanName();
//调用3,3-1-1-1-2-3-1-1向IOC 容器注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//如果解析的BeanDefinition 有别名,向容器为其注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
//调用3,3-1-1-1-2-3-1-1向IOC 容器注册BeanDefinition 实现类 DefaultListableBeanFactory
//存储注册信息的BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//向IOC 容器注册解析的BeanDefiniton,这里并没有注册实例化bean;
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//校验解析的BeanDefiniton不为抽象类 未重复
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}else {
if (hasBeanCreationStarted()) {
//注册的过程中需要线程同步,以保证数据的一致性(完成了IOC容器初始化)
//这里beanDefinitionMap 为ConcurrentHashMap为何还需要锁? 因为其中的put、contains、remove不是原子性操作;
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//检查是否有同名的BeanDefinition 已经在IOC 容器中注册
if (oldBeanDefinition != null || containsSingleton(beanName)) {
//重置所有已经注册过的BeanDefinition 的缓存
resetBeanDefinition(beanName);
}
}
使用SpringIOC服务: spring提供声明式载入web应用程序来存储ServletContext;
最后,我们的Spring IOC容器就初始化好了,初始化好了之后,这里我们的Bean还没有真正的实例化,在容器中保管的仅仅是BeanDefinition,后面的实例化过程和依赖注入又是怎么实现的呢?
阿里大佬带看源码链接:请点击这里