栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring阅读(3)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring阅读(3)

refreshBeanFactory()
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, Set actualResources) 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;
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353666.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号