obtainFreshBeanFactory()方法是refresh()方法中的核心之一。
作用:初始化beanFactory,加载并解析配置
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//1.初始化beanFactory,并执行加载和解析配置操作
refreshBeanFactory();
//返回beanFactory实例
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
obtainFreshBeanFactory()方法中做了二件事:
初始化beanFactory,并执行加载和解析配置操作
进入到refreshBeanFactory()方法,分析refreshBeanFactory()方法的具体实现:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
...
@Override
protected final void refreshBeanFactory() throws BeansException {
//判断是否存在beanFactory
if (hasBeanFactory()) {
// 注销所有的单例
destroyBeans();
//重置beanFactory
closeBeanFactory();
}
try {
//创建beanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//指定序列化id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
beanFactory.setSerializationId(getId());
//定制BeanFactory
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
...
}
refreshBeanFactory()方法中做了四件事情:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
...
/** Bean factory for this context */
@Nullable
private DefaultListableBeanFactory beanFactory;
...
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
}
}
如果this.beanFactory != null,则注销所有的单例和重置beanFactory。
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
进去到destroySingletons():
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
...
@Override
public void destroySingletons() {
//调用父类的销毁方法销毁单例bean
super.destroySingletons();
//清空手工注册的beanName的缓存
this.manualSingletonNames.clear();
//清空类型-->beanName的映射缓存
clearByTypeCache();
}
}
父类的销毁方法,destroySingletons():
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
...
public void destroySingletons() {
if (logger.isDebugEnabled()) {
logger.debug("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
//设置正在销毁的标记为true
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
//遍历销毁之前注册的所有disposableBean
destroySingleton(disposableBeanNames[i]);
}
//清空beanName --> 它包含的所有内部beanName集合的映射缓存
this.containedBeanMap.clear();
//清空beanName --> 它依赖的所有beanName集合的映射缓存
this.dependentBeanMap.clear();
//清空beanName --> 依赖它的所有beanName集合的映射缓存
this.dependenciesForBeanMap.clear();
//清空所有注册的缓存
clearSingletonCache();
}
//clearSingletonCache():清空所有注册的缓存的方法
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
// 清空单例bean缓存
this.singletonObjects.clear();
// 清空单例工厂缓存
this.singletonFactories.clear();
// 清空提前暴露的beanName --> bean的映射缓存
this.earlySingletonObjects.clear();
// 清空已经注册的单例bean缓存
this.registeredSingletons.clear();
// 设置正在销毁的标记为false
this.singletonsCurrentlyInDestruction = false;
}
}
...
}
destroySingleton():销毁之前注册的所有disposableBean
public void destroySingleton(String beanName) {
//清除bean的相应缓存
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
//移除并获取disposableBean
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
//销毁
destroyBean(beanName, disposableBean);
}
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isDebugEnabled()) {
logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
// 首选递归销毁所有当前bean依赖的bean
destroySingleton(dependentBeanName);
}
}
if (bean != null) {
try {
//销毁bean
bean.destroy();
}
catch (Throwable ex) {
logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
// 递归销毁当前bean包含的所有内部bean
destroySingleton(containedBeanName);
}
}
synchronized (this.dependentBeanMap) {
// 遍历找出所有依赖当前bean的列表,将当前bean从被依赖的列表中移除
for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Set<String>> entry = it.next();
Set<String> dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// 从所有依赖当前bean的映射中移除依赖关系
this.dependenciesForBeanMap.remove(beanName);
}
@Override
protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}
}
该方法令beanFactory置为null。
进入到createBeanFactory()方法中:
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
调试发现:getInternalParentBeanFactory() == null,因此创建DefaultListableBeanFactory。
beanFactory.setSerializationId(getId());
//其中getId():
@Override
public String getId() {
return this.id;
}
//this.id为:
private String id = ObjectUtils.identityToString(this);
对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//是否允许覆盖同名称的不同定义的对象
if (this.allowBeanDefinitionOverriding != null) {
// 如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//是否允许bean之间存在循环依赖
if (this.allowCircularReferences != null) {
// 如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
...
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//为指定beanFactory创建XmlBeanDefinitionReader(加载解析bean)
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//对beanDefinitionReader进行环境变量的设置
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//对beanDefinitionReader进行设置,空方法
initBeanDefinitionReader(beanDefinitionReader);
//设置loadBeanDefinitions的配置文件
loadBeanDefinitions(beanDefinitionReader);
}
...
}
进入到initBeanDefinitionReader(beanDefinitionReader)中:
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
}
发现啥都没有,纯粹是给子类重写的。
进入到loadBeanDefinitions()方法中:
//XmlWebApplicationContext
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
//获取配置位置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
查看getConfigLocations()方法:
@Nullable
protected String[] getConfigLocations() {
return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}
调试发现:configLocations = [“classpath:spring.xml”]。
getConfigLocations()为什么等于"classpath:spring.xml"?
细心的同学应在spring源码解析(一)中发现了线索:
在configureAndRefreshWebApplicationContext()方法中
//读取web.xml中Spring配置文件路径CONFIG_LOCATION_PARAM = “contextConfigLocation”
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
如果this.configLocations为null,则进入getDefaultConfigLocations()方法,而XmlWebApplicationContext类中重写了AbstractRefreshableConfigApplicationContext类中的getDefaultConfigLocations()方法:
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
...
@Override
protected String[] getDefaultConfigLocations() {
if (getNamespace() != null) {
// "/WEB-INF/xxx.xml"
return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
}
else {
// "/WEB-INF/applicationContext.xml"
return new String[] {DEFAULT_CONFIG_LOCATION};
}
}
}
其中:
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
因此,如果不在web.xml中设置contextConfigLocation的话,就会读取默认contextConfigLocation的值为:"/WEB-INF/applicationContext.xml"。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
继续进入reader.loadBeanDefinitions(configLocation)里面:
//抽象类AbstractBeanDefinitionReader
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
继续进入,为每个bean生成BeanDefinition
//抽象类AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取资源
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
//resourceLoader是ClasspathXmlApplicationContext,ApplicationContext接口本身继承了ResourcePatternResolver接口
if (resourceLoader instanceof ResourcePatternResolver) {
try {
//location转为Resource完成定位工作
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
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.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
@Override
@Nullable
public ResourceLoader getResourceLoader() {
return this.resourceLoader;
}
this.resourceLoader的是从哪里获取的?
细心的同学看上面的《5. loadBeanDefinitions():加载bean定义》中有这么一句:
beanDefinitionReader.setResourceLoader(this);
//点击进去:
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
其中的this就是XmlWebApplicationContext上下文。
esource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location)将location转成了Resource[],这一步完成了资源的定位工作。
它调用了PathMatchingResourcePatternResolver的getResources方法:
@Override
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
//是否以classpath*:开头
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
return findPathMatchingResources(locationPattern);
}
else {
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
locationPattern.indexOf(':') + 1);
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
return findPathMatchingResources(locationPattern);
}
else {
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}
根据location写法,解析方式也不同:
前缀为classpath*
前缀为classpath
把读取的"classpath:spring.xml"转换成resource之后,加载bean:loadBeanDefinitions(resources);
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
以上是多个资源遍历加载,继续进入到loadBeanDefinitions(resource)中:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//读取encodedResource流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//继续加载bean的定义
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
进入到doLoadBeanDefinitions(inputSource, encodedResource.getResource())中:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
这里把读取的"classpath:spring.xml"转换成的resource转换成Document文件,进入registerBeanDefinitions(doc, resource):
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
进入到documentReader.registerBeanDefinitions(doc, createReaderContext(resource));中:
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
继续doRegisterBeanDefinitions(root);:
protected void doRegisterBeanDefinitions(Element root) {
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;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
进入到parseBeanDefinitions(root, this.delegate)中,此方法就是解析xml的方法:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
如图中所显示,解析web.xml中的spring.xml时读取到
其中delegate.isDefaultNamespace(ele)进入查看下是什么意思:
public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
public boolean isDefaultNamespace(@Nullable String namespaceUri) {
return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));
}
public boolean isDefaultNamespace(Node node) {
return isDefaultNamespace(getNamespaceURI(node));
}
这个判断条件的意思就是判断spring.xml中是否有http://www.springframework.org/schema/beans(bean、beans、import、alias)定义的存在。
如果存在,则进入到parseDefaultElement(ele, delegate)中:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
这里是四种判断条件:
public static final String IMPORT_ELEMENT = "import";
public static final String ALIAS_ELEMENT = "alias";
public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
(public static final String BEAN_ELEMENT = "bean";)
public static final String NESTED_BEANS_ELEMENT = "beans";
getBeanFactory()方法的内容如下:
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
直接返回当前上下文的beanFactory。
上一章:spring源码解析(二):refresh()源码解析
下一章:spring源码解析(四):refresh()中obtainFreshBeanFactory()(1、解析spring.xml))