protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
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);
}
}
hasBeanFactory
同步了this.beanFactoryMonitor对象,返回spring容器是否拥有beanFactory 类型为DefaultListableBeanFactory 可以简单理解为糖果加工厂,beanDefinition可以理解为组装好原材料,最后实例化bean的时候可以理解为将beanDefinition加工为糖果
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
}
如果已经初始化过bean工厂 那么销毁所有bean 然后关闭bean工厂
if (hasBeanFactory()) {
// 将DefaultListableBeanFactory的属性的clear方法进行清空操作
destroyBeans();
// 将bean工厂序列号id,beanFactory置空
closeBeanFactory();
}
createBeanFactory
该方法通过DefaultListableBeanFactory 有参构造函数返回了一个实例 ,getInternalParentBeanFactory方法 获取内部bean工厂父容器,因为spring已经是父容器了 所以该方法返回null
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
beanFactory.setSerializationId(getId());
getId返回了能够标识容器的唯一id 默认是ApplicationContext类的名称+@+容器的内存地址 。也可以在web.xml中配置contextId变量 必须确保唯一,因为setSerializationId方法会以serializationId 为key value为bean工厂
public void setSerializationId(String serializationId) {
if (serializationId != null) {
serializableFactories.put(serializationId, new WeakReference(this));
}
else if (this.serializationId != null) {
serializableFactories.remove(this.serializationId);
}
this.serializationId = serializationId;
}
customizeBeanFactory(beanFactory);
这里可以看见 对两个参数进行了判断 如果不为null就set进去
allowBeanDefinitionOverriding
是否允许存在相同名称的bean,如果存在,后者覆盖前者。
allowCircularReferences属性含义
是否允许循环依赖,如果允许 则进行自动循环依赖注入
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
可以找到AbstractRefreshableApplicationContext类提供了set方法
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
public void setAllowCircularReferences(boolean allowCircularReferences) {
this.allowCircularReferences = allowCircularReferences;
}
还记得spring预留的initPropertySources空方法吗 我们仍然可以在此进行赋值,或者重写customizeBeanFactory方法 在调用父类customizeBeanFactory方法之前将属性设置为true
public class MyClassPathApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathApplicationContext(String s) {
super(s);
}
@Override
protected void initPropertySources() {
// getEnvironment().setRequiredProperties("test");
this.setAllowBeanDefinitionOverriding(true);
this.setAllowCircularReferences(true);
}
@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
this.setAllowBeanDefinitionOverriding(true);
this.setAllowCircularReferences(true);
super.customizeBeanFactory(beanFactory);
}
}
loadBeanDefinitions(beanFactory);
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
首先new了一个XmlBeanDefinitionReader 可以理解成可以将xml转换为多个BeanDefinition的阅读器
内部赋值了registry为bean工厂 因为DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
并且两个判断都走了else 这里可以看出阅读器是根据PathMatchingResourcePatternResolver 路径匹配来解析的
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// Determine ResourceLoader to use.
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
配置了当前环境,资源装载器,并设置实体解析器为ResourceEntityResolver。都是为了解析xml
beanDefinitionReader.setEnvironment(getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));initBeanDefinitionReader(beanDefinitionReader);
initBeanDefinitionReader是个spring预留的空方法,方便用户自定义xml读取器,例如关闭xml验证 或者使用其他xml转换器
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
}
loadBeanDefinitions(beanDefinitionReader);
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
获取spring配置文件的路径,也就是web.xml中配置文件中contextConfigLocation的值
protected String[] getConfigLocations() {
return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}
然后再循环配置 调用阅读器的loadBeanDefinitions方法
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
这里调用的是父类AbstractBeanDefinitionReader.loadBeanDefinitions方法 actualResources参数为null
public int loadBeanDefinitions(String location, SetactualResources) throws BeanDefinitionStoreException { 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 { 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; } }



