1.obtainFreshBeanFactory()
该方法会调用org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();//刷新 bean factory,进入此方法查看
return getBeanFactory();
}
2.refreshBeanFactory()
该方法,有两个实现,进入org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
// 1.判断是否已有bean factory
if (hasBeanFactory()) {
destroyBeans();// 销毁 beans
closeBeanFactory();// 关闭 bean factory
}
try {
// 2.实例化 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 3. 设置序列化id 并建立起id和该 bean factory 实例的映射关系
beanFactory.setSerializationId(getId());
// 4.自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
customizeBeanFactory(beanFactory);
//TODO 5.加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 赋值当前bean facotry
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
2.1 首先判断是否存在BeanFactory,如果存在则销毁并关闭BeanFactory
2.2 然后在实例化BeanFactory,这里实现的是DefaultListableBeanFactory
2.3 设置序列化ID,与BeanFactory建立映射关系
2.4 自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
2.5 加载应用中的BeanDefinitions
3.loadBeanDefinitions(beanFactory)
该方法有4个实现,进入 org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 给指定的beanFactory创建一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象
// 3.1XmlBeanDefinitionReader的初始化
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 将context加载了资源的environment配置给bean definition reader
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 将 ResourceLoader换成 AbstractXmlApplicationContext 对象 AbstractXmlApplicationContext 实现了 ResourceLoader 接口
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 提供给子类实现提供一些自定义的初始化策略
initBeanDefinitionReader(beanDefinitionReader);
//TODO 3.2加载beanDefinition操作
loadBeanDefinitions(beanDefinitionReader);
}
3.1 初始化一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象,并给该读取器设置一些属性
3.2 加载beanDefinitions
4.loadBeanDefinitions(beanDefinitionReader)
解析配置文件
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 从Resource资源对象加载BeanDefinitions
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 从xml配置文件加载BeanDefinition对象
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//4.2加载解析beanDefinitions
reader.loadBeanDefinitions(configLocations);
}
}
...
@Override
//4.2.1 从xml配置文件加载BeanDefinition对象
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
// 如果有多个配置文件,循环读取加载,并统计总共加载了多少个BeanDefinition
for (String location : locations) {
//加载
count += loadBeanDefinitions(location);
}
return count;
}
...
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
5.loadBeanDefinitions(location, null)
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 5.1获取上下文的资源加载器 AbstractXmlApplicationContext
/**这里其实是获取 AbstractBeanDefinitionReader 的ResourceLoader,XmlBeanDefinitionReader继承bstractBeanDefinitionReader
* 在{@link org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)}
* 中beanDefinitionReader.setResourceLoader(this) <>AbstractXmlApplicationContext</>;
* AbstractXmlApplicationContext的继承体系中有ResourcePatternResolver
*/
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
// 5.2判断资源加载器是否 ResourcePatternResolver 类型(xml、url等不同类型统一接口为匹配类型)
//ApplicationContext接口也有继承ResourcePatternResolver接口
if (resourceLoader instanceof ResourcePatternResolver) {
try {
// 统一加载转换为Resource资源对象
// 5.3通过路径获取 资源处理器 数组
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 加载资源中配置的BeanDefinition对象,并返回数量
/**@see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
* 委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
* */
//TODO 5.4通过 资源处理器 加载 BeanDefinitions
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
...
}
...
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
//5.4.1 调用的子类XmlBeanDefinitionReader方法
count += loadBeanDefinitions(resource);
}
return count;
}
...
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//5.4.2 将读取的xml资源进行编码处理
return loadBeanDefinitions(new EncodedResource(resource));
}
5.1 获取上下文的资源加载器 AbstractXmlApplicationContext
5.2 判断资源加载器是否 ResourcePatternResolver 类型(xml、url等不同类型统一接口为匹配类型)
5.3 统一加载转换为Resource资源对象
5.4 通过资源处理器 加载 BeanDefinitions
6.loadBeanDefinitions(EncodedResource encodedResource)
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
...
try {
//1.首先调用EncodedResource#getResource去获取封装的资源resource,这里拿到的是classPathResource对象
//然后在调用Resource#getInputStream获取一个inputStream
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 把xml文件流封装为InputSource对象
InputSource inputSource = new InputSource(inputStream);
//保存对应编码
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//TODO 2.do!执行加载逻辑
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
...
}
6.1 首先调用EncodedResource#getResource去获取封装的资源resource,这里拿到的是classPathResource对象,然后在调用Resource#getInputStream获取一个inputStream,把inputStream文件流封装为InputSource对象
6.2 do!执行加载BeanDefinitions逻辑
7.doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
// 读取xml信息,将xml中信息保存到Document对象
Document doc = doLoadDocument(inputSource, resource);
//TODO 解析document对象,封装BeanDefinition对象并进行注册
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
...
}
...
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//getRegistry()方法拿的是bean工厂对象,beanDefinition注册在工厂中
//这个方法就是返回已经被注册在工厂中的beanDefinitions数量
int countBefore = getRegistry().getBeanDefinitionCount();
// TODO 注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回新注册的BeanDefinition数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
7.1 读取xml信息,将xml中信息保存到Document对象
7.2 解析document对象,封装BeanDefinition对象并进行注册
7.3 注册BeanDefinition
8.registerBeanDefinitions()
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
...
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
...
//xml预处理,子类没有重写里面就是空实现
preProcessXml(root);
//TODO 解析xml
parseBeanDefinitions(root, this.delegate);
//xml后处理,子类没有重写里面就是空实现
postProcessXml(root);
this.delegate = parent;
}
...
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//默认名称空间是"http://www.springframework.org/schema/beans"
//进入条件
if (delegate.isDefaultNamespace(root)) {
//获取根元素下的子Node,注意,Node不一定是子标签,可能是回车,可能是注释
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
//拿到了<beans>下的子标签
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//8.1 如果该标签属于beans的名称空间,则进入这个方法
//xmlns="http://www.springframework.org/schema/beans"
parseDefaultElement(ele, delegate);
}
else {
//TODO 解析自定义标签元素
//8.2 如果该标签属于其他的名称空间比如:context,aop等
//xmlns:aop="http://www.springframework.org/schema/aop"
//xmlns:context="http://www.springframework.org/schema/context"
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
8.1 解析bean标签
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// import元素处理
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// alias 元素处理
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 8.1.1 bean 元素处理(以该元素为例)
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 嵌套 beans 处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
8.1.1 bean 元素处理
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析bean元素为BeanDefinition,但是此时使用 BeanDefinitionHolder 又包装成了 BeanDefinitionHolder 对象
//1 通过代理解析bean元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
/*
<bean id="demo" class="com.chenhao.spring.MyTestBean">
<property name="beanName" value="bean demo1"/>
<meta key="demo" value="demo"/>
<mybean:username="mybean"/>
</bean>
如果有自定义标签,则处理自定义标签
*/
//2 如果有要求的话渲染beanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 完成BeanDefinition的注册
//3 注册最终被渲染的实例到工厂中(进入该方法)
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
1.通过BeanDefinitionHolder代理解析bean元素
2.如果有要求的话渲染beanDefinition
3.注册最终被渲染的实例到工厂中
8.1.1.3 注册BeanDefinition
到此BeanDefinition已经完成了注册
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
/**@see org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition)*/
// 1.注册bean definition的beanName 比如tk.mybatis.spring.mapper.MapperScannerConfigurer#0
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//2.为bean名称注册别名(如果有的话)。
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
...
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
...
else {
//这里面代表beanName还没有被注册
//然后根据阶段不同又有一层判断
if (hasBeanCreationStarted()) {
//这个阶段是bean已经开始创建
// Cannot modify startup-time collection elements anymore (for stable iteration)
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;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
// 仍然处于启动时的注册阶段
// 所以这里走这个方法
//beanDefinitionMap是工厂的一个属性,ConcurrentHashMap类型
//他保存所有解析好的bean Definition的名称和实例的映射
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanName也单独使用了一个ArrayList来保存,方便遍历
this.beanDefinitionNames.add(beanName);
//如果该bean definition是手动注册的,还要从manualSingletonNames中
//移除bean definition的beanName,还要从manualSingletonNames中是LinkedHashSet
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
8.2 解析自定义标签
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//拿到标签对应的名称空间URI
//比如:http://www.springframework.org/schema/aop
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//TODO 8.2.1 拿到名称空间处理器解析器,去解析URI,获取名称空间处理器
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//8.2.2 通过处理器的某个解析器解析对应标签
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
8.2.1 获取对应命名空间的处理器
public NamespaceHandler resolve(String namespaceUri) {
//8.2.1.1 拿到处理器解析器中所有的处理器(进入该方法)
//http://www.springframework.org/schema/aop --> org.springframework.aop.config.AopNamespaceHandler
Map<String, Object> handlerMappings = getHandlerMappings();
//拿到指定的处理器
Object handlerOrClassName = handlerMappings.get(namespaceUri);
//如果为null就返回null
if (handlerOrClassName == null) {
return null;
}
//如果是实例就返回实例
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
//否则就一定是字符串
String className = (String) handlerOrClassName;
try {
//通过加载器生成处理器的Class对象
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
//必须要实现NamespaceHandler接口
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
//实例化一个
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//8.2.1.2 TODO 初始化,进入这个方法,里面初始化多个解析器
namespaceHandler.init();
//用实例覆盖原先handlerMappings中的字符串
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
}
8.2.1.1 拿到处理器解析器中所有的处理器
private Map<String, Object> getHandlerMappings() {
/**这里需要注意 如果idea的setting->degugger中关于toString的配置是勾选的话
* 在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}
* 中执行createReaderContext(resource)方法时会调用toString方法 从而给 handlerMappings 赋值
*/
Map<String, Object> handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
synchronized (this) {
handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
if (logger.isTraceEnabled()) {
logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
}
try {
/** handlerMappingsLocation 数据来源
* 在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}初始化
* {@link XmlBeanDefinitionReader#createReaderContext(Resource)}
* {@link XmlBeanDefinitionReader#getNamespaceHandlerResolver()}
*/
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isTraceEnabled()) {
logger.trace("Loaded NamespaceHandler mappings: " + mappings);
}
handlerMappings = new ConcurrentHashMap<>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return handlerMappings;
}
1.这里需要注意 如果idea的setting->degugger中关于toString的配置是勾选的话在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}中执行createReaderContext(resource)方法时会调用toString方法 从而给 handlerMappings 赋值。
2.handlerMappingsLocation 数据来源,调用链在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)} >> {@link XmlBeanDefinitionReader#createReaderContext(Resource)} >>{@link XmlBeanDefinitionReader#getNamespaceHandlerResolver()}
8.2.1.2 初始化多个解析器 namespaceHandler.init()
该方法有多个实现,进入aop的实现AopNamespaceHandler
public void init() {
//这里面每一个解析器都对应着AOP名称空间下的一个标签
//不同的处理器注册的解析器都不一样
//这里随便找一个解析器,查看他的注册流程(aspectj-autoproxy)8.2.2
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
...
//aspectj-autoproxy 在8.2.2中会调用parse方法
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
8.2.2 通过处理器的某个解析器解析对应标签
public BeanDefinition parse(Element element, ParserContext parserContext) {
//将标签名称作为key,去处理器内部的parsers属性中,获取对应的value值,也就是解析器
BeanDefinitionParser parser = findParserForElement(element, parserContext);
//调用解析方法
return (parser != null ? parser.parse(element, parserContext) : null);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
//element存放了从xml中解析的信息(以aspectj-autoproxy为例)
String localName = parserContext.getDelegate().getLocalName(element);
/**parsers {@link org.springframework.aop.config.AopNamespaceHandler#init()}*/
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
1.根据传入的element获取对应的解析器,以aspectj-autoproxy为例
2.获取element中标签的名称,然后在根据名称去parser中获取对应解析器
3.调用解析方法parse,后面的步骤主要是注册BeanDefinition