01 XmlBeanFactory继承自DefaultListableBeanFactory
public class XmlBeanFactory extends DefaultListableBeanFactory {
//xml读取器
private final XmlBeanDefinitionReader reader;
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
this.reader.loadBeanDefinitions(resource);
}
}
02 从FileSystemXmlApplicationContext入手认识ApplicationContext
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
public FileSystemXmlApplicationContext() {
}
public FileSystemXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, (ApplicationContext)null);
}
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, (ApplicationContext)null);
}
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
this.refresh();
}
}
protected Resource getResourceByPath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
}
03 IOC的初始化由ApplicationContext中的构造器中调用refresh()启动的。具体来说,包括Bean的Resouce定位(资源定位)、载入、注册 三个基本过程。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
//这里初始化IOC
this.refresh();
}
}
04 以FileSystemXmlApplicationContext为例观察Bean的Resouce定位过程,以下是类关系图。FileSystemXmlApplicationContext继承自AbstractXmlApplicationContext类
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
//0 这里初始化IOC,从这里开始
this.refresh();
}
}
//org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
//1 这里获取beanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
...略
}
}
//org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//2 这里刷新beanFactory
this.refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
...略
}
//org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
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);
//3 这里调用loadBeanDefinitions
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var4) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var4);
}
}
//org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
//4 这里
this.loadBeanDefinitions(beanDefinitionReader);
}
//org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
//5 这里
reader.loadBeanDefinitions(configLocations);
}
}
//org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String[])
public int loadBeanDefinitions(String[] locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
String[] var6 = locations;
int var5 = locations.length;
for(int var4 = 0; var4 < var5; ++var4) {
String location = var6[var4];
//6 这里
counter += this.loadBeanDefinitions(location);
}
return counter;
}
//org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
//7 注意这里获取的是默认资源加载器
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
} else {
int loadCount;
if (!(resourceLoader instanceof ResourcePatternResolver)) {
Resource resource = resourceLoader.getResource(location);
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
} else {
try {
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
loadCount = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Resource[] var9 = resources;
int var8 = resources.length;
for(int var7 = 0; var7 < var8; ++var7) {
Resource resource = var9[var7];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
}
}
}
}
//8 resourceLoader作为类AbstractBeanDefinitionReader的属性
org.springframework.beans.factory.support.AbstractBeanDefinitionReader#getResourceLoader
public ResourceLoader getResourceLoader() {
return this.resourceLoader;
}
//9 这里的 registry传入的是DefaultListableBeanFactory类,它不属于ResourceLoader
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader)this.registry;
} else {
//DefaultListableBeanFactory不属于ResourceLoader,所以走这里
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
}
//10 默认资源加载器
public PathMatchingResourcePatternResolver() {
this.resourceLoader = new DefaultResourceLoader();
}
//11 获取默认类加载器
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}