当前位置: 代码迷 >> 综合 >> spring refresh()方法详解2之obtainFreshBeanFactory()
  详细解决方案

spring refresh()方法详解2之obtainFreshBeanFactory()

热度:44   发布时间:2024-02-08 21:10:16.0

 obtainFreshBeanFactory方法实现代码如下:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 1.刷新 BeanFactory --具体实现见AbstractRefreshableApplicationContextrefreshBeanFactory();// 2.返回刷新后的 BeanFactoryreturn getBeanFactory();}

1 refreshBeanFactory方法

	/*** 刷新 BeanFactory*/@Overrideprotected final void refreshBeanFactory() throws BeansException {// 1.判断是否已经存在 BeanFactory,如果存在则先销毁、关闭该 BeanFactory// 注意,应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前// ApplicationContext 是否有 BeanFactoryif (hasBeanFactory()) {destroyBeans();	//销毁所有 BeancloseBeanFactory();//关闭 BeanFactory}try {// 2.创建一个新的BeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());	// 用于 BeanFactory 的序列化// 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用customizeBeanFactory(beanFactory);// 3.加载 bean 定义。loadBeanDefinitions(beanFactory);	//AbstractXmlApplicationContext类中实现synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}

1.1 判断beanFactory是否存在,若存在先销毁关闭

1.hasBeanFactory 判断beanFactory是否已存在,我们第一次启动时hasBeanFactory 应该是返回false

	/** Synchronization monitor for the internal BeanFactory. */private final Object beanFactoryMonitor = new Object();/*** 判断beanFactory是否存在*/protected final boolean hasBeanFactory() {synchronized (this.beanFactoryMonitor) { //加锁return (this.beanFactory != null);	//直接返回beanFactory 是否为null}}

2.destroyBeans销毁所有已创建bean,我们直接ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");启动容器是不会执行到该方法的,但是启动后调用context.refresh();会进入到条件中执行该方法。

	/*** 销毁所有bean  前提条件:beanFactory存在*/protected void destroyBeans() {//getBeanFactory 在AbstractRefreshableApplicationContext中实现//destroySingletons 在DefaultListableBeanFactory中实现getBeanFactory().destroySingletons();}
//========================AbstractRefreshableApplicationContext > getBeanFactory===========/*** 获取beanFactory*/@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {synchronized (this.beanFactoryMonitor) {//加锁if (this.beanFactory == null) {	//判断是否为null 为null则抛出异常throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}return this.beanFactory;	//返回beanFactory}}
//========================DefaultListableBeanFactory > destroySingletons===========/*** DefaultListableBeanFactory--销毁bean*/@Overridepublic void destroySingletons() {super.destroySingletons();	//调用父类方法销毁Singletons的Bean//更新ManualSingletonNamesupdateManualSingletonNames(Set::clear, set -> !set.isEmpty());clearByTypeCache();	//清空ByType的缓存}

下面分析destroySingletons方法

2.1 super.destroySingletons()

	/*** DefaultSingletonBeanRegistry:销毁所有单例bean*/public void destroySingletons() {if (logger.isTraceEnabled()) {logger.trace("Destroying singletons in " + this);}synchronized (this.singletonObjects) {	//加锁this.singletonsCurrentlyInDestruction = true;	//标记设置为true}String[] disposableBeanNames;	//所有待销毁的beanNamesynchronized (this.disposableBeans) {	//加锁//拿出disposableBeans中的所有key,放入disposableBeanNames数组中disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());	}//遍历disposableBeanNames数组 调用destroySingleton方法销毁beanfor (int i = disposableBeanNames.length - 1; i >= 0; i--) {destroySingleton(disposableBeanNames[i]);}//清空以下几个集合this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();clearSingletonCache();}/*** 调用clearSingletonCache方法清空单例的缓存*/protected void clearSingletonCache() {synchronized (this.singletonObjects) {this.singletonObjects.clear();this.singletonFactories.clear();this.earlySingletonObjects.clear();this.registeredSingletons.clear();this.singletonsCurrentlyInDestruction = false;}}

2.2 updateManualSingletonNames(Set::clear, set -> !set.isEmpty())

	/*** 先判断manualSingletonNames是否为空,* 	不为空则根据manualSingletonNames新建一个set,然后把这个set清空,然后在把manualSingletonNames指向这个set* @param action 一个消费型接口  这里是Set::clear  调用Set的clear方法* @param condition	一个断言型接口	这里是set -> !set.isEmpty()  判断set是否非空*/private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {if (hasBeanCreationStarted()) {	//判断alreadyCreated是否非空synchronized (this.beanDefinitionMap) {	//加锁if (condition.test(this.manualSingletonNames)) {	//断言manualSingletonNames是否非空//根据manualSingletonNames新建一个LinkedHashSet  updatedSingletonsSet<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);action.accept(updatedSingletons); //对updatedSingletons进行消费  清空updatedSingletonsthis.manualSingletonNames = updatedSingletons;//将manualSingletonNames指向消费后的updatedSingletons 是一个空集合}}}else {//alreadyCreated为空if (condition.test(this.manualSingletonNames)) {//断言manualSingletonNames 如果manualSingletonNames非空action.accept(this.manualSingletonNames);	//对manualSingletonNames进行消费	清空manualSingletonNames}}}

2.3 clearByTypeCache()

	/*** 清空allBeanNamesByType与singletonBeanNamesByType两个集合*/private void clearByTypeCache() {this.allBeanNamesByType.clear();this.singletonBeanNamesByType.clear();}

3 closeBeanFactory 关闭 BeanFactory

	/*** 关闭 BeanFactory*/@Overrideprotected final void closeBeanFactory() {synchronized (this.beanFactoryMonitor) {	//加锁if (this.beanFactory != null) {	//beanFactory非空this.beanFactory.setSerializationId(null);	//清空集合序列化ID this.beanFactory = null;	//置空beanFactory}}}
//==================================================================================/*** 设置集合序列化ID */public void setSerializationId(@Nullable String serializationId) {if (serializationId != null) {	//serializationId非空serializableFactories.put(serializationId, new WeakReference<>(this));	//put}else if (this.serializationId != null) {	//this.serializationId非空serializableFactories.remove(this.serializationId);	//remove}this.serializationId = serializationId;	//设置this.serializationId 为 serializationId}

1.1.2 创建一个新的BeanFactory并设置其属性

1.createBeanFactory创建BeanFactory

	/*** 创建BeanFactory*/protected DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory(getInternalParentBeanFactory());}/*** 获取父BeanFactory */@Nullableprotected BeanFactory getInternalParentBeanFactory() {return (getParent() instanceof ConfigurableApplicationContext ?((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());}

2.beanFactory.setSerializationId(getId());    // 用于 BeanFactory 的序列化

3.customizeBeanFactory设置 BeanFactory 的两个配置属性

	/*** beanFactory配置*/protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {if (this.allowBeanDefinitionOverriding != null) {// 是否允许 Bean 定义覆盖beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.allowCircularReferences != null) {// 是否允许 Bean 间的循环依赖beanFactory.setAllowCircularReferences(this.allowCircularReferences);}}

1.3 加载 bean 定义

	/*** 加载 bean 定义*/@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// 1.为指定BeanFactory创建XmlBeanDefinitionReaderXmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// 2.使用此上下文的资源加载环境配置 XmlBeanDefinitionReaderbeanDefinitionReader.setEnvironment(this.getEnvironment());// resourceLoader赋值为XmlWebApplicationContextbeanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// 初始化 BeanDefinitionReaderinitBeanDefinitionReader(beanDefinitionReader);// 3.加载 bean 定义loadBeanDefinitions(beanDefinitionReader);}

1.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory)

        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//======================================================================public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {super(registry);}
//======================================================================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 possibleif (this.registry instanceof EnvironmentCapable) {this.environment = ((EnvironmentCapable) this.registry).getEnvironment();}else {this.environment = new StandardEnvironment();}}

主要是初始化registry,resourceLoader和environment,我们这里new ClassPathXmlApplicationContext("spring.xml")启动容器的方式两个判断条件都会走到else里。

2.主要是对beanDefinitionReader进行各种配置

3.loadBeanDefinitions(beanDefinitionReader)加载 bean 定义,代码如下:

	/*** 加载 bean 定义*/protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {//获取资源ResourceResource[] configResources = getConfigResources();if (configResources != null) {// 根据Resource加载 bean 定义reader.loadBeanDefinitions(configResources);}// 1.获取配置文件路径String[] configLocations = getConfigLocations();if (configLocations != null) {//2根据配置文件configLocations加载bean定义reader.loadBeanDefinitions(configLocations);}}/*** 这里直接返回null*/@Nullableprotected Resource[] getConfigResources() {return null;}@Nullableprotected String[] getConfigLocations() {return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());}

我们这里追一下reader.loadBeanDefinitions(String [] configLocations)的源码

	/*** 根据配置文件路径加载*/@Overridepublic int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {Assert.notNull(locations, "Location array must not be null");	//校验非nullint count = 0;for (String location : locations) {	//遍历count += loadBeanDefinitions(location);	//根据location加载bean定义}return count;}@Overridepublic int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {return loadBeanDefinitions(location, null);}/*** 加载bean定义*/public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {ResourceLoader resourceLoader = getResourceLoader();	//获取ResourceLoaderif (resourceLoader == null) {throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");}if (resourceLoader instanceof ResourcePatternResolver) {	//resourceLoader是否为ResourcePatternResolver类型try {//根据resourceLoader获取ResourceResource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);int count = loadBeanDefinitions(resources);	//调用loadBeanDefinitions(Resource[] resources)if (actualResources != null) {Collections.addAll(actualResources, resources);	//将resources中数据添加到actualResources中}if (logger.isTraceEnabled()) {logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");}return count;	//返回}catch (IOException ex) {throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex);}}else {Resource resource = resourceLoader.getResource(location);	//获取Resourceint count = loadBeanDefinitions(resource);	//加载bean定义if (actualResources != null) {actualResources.add(resource);//resource添加到actualResources中}if (logger.isTraceEnabled()) {logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");}return count;//返回}}

这里我们发现会调用loadBeanDefinitions(resources);或loadBeanDefinitions(resource);参数是Resource类型或Resource[] 类型继续追源码

	/*** 根据Resource加载bean定义*/@Overridepublic int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {Assert.notNull(resources, "Resource array must not be null");	//null校验int count = 0;for (Resource resource : resources) {	//遍历count += loadBeanDefinitions(resource);	//根据resource加载bean定义}return count;}/*** 根据Resource加载bean定义*/@Overridepublic int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {return loadBeanDefinitions(new EncodedResource(resource));}/*** 根据EncodedResource加载bean定义*/public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {Assert.notNull(encodedResource, "EncodedResource must not be null");	//null校验if (logger.isTraceEnabled()) {logger.trace("Loading XML bean definitions from " + encodedResource);}//从resourcesCurrentlyBeingLoaded中get数据Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet<>(4);	//currentResources为空就初始化一个this.resourcesCurrentlyBeingLoaded.set(currentResources);	//currentResources放入resourcesCurrentlyBeingLoaded中}if (!currentResources.add(encodedResource)) {	//添加encodedResource  若添加失败 直接抛出异常throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}try {InputStream inputStream = encodedResource.getResource().getInputStream();	//获取输入流try {InputSource inputSource = new InputSource(inputStream);	//包装成InputSourceif (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());	//设置格式}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();}}}/*** 加载bean定义*/protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);	//转换成Document结构int count = registerBeanDefinitions(doc, resource);	//加载数据if (logger.isDebugEnabled()) {logger.debug("Loaded " + count + " bean definitions from " + resource);}return count;}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);}}

继续追溯源码吧

	/*** 加载bean定义*/public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {//获取BeanDefinitionDocumentReaderBeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//获取注册表中定义的bean的数目int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;	//计算成功加载数量}@Overridepublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;doRegisterBeanDefinitions(doc.getDocumentElement());	//加载操作}/*** 加载bean定义*/@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)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.isDebugEnabled()) {logger.debug("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;}/*** 加载操作*/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) {	//子节点是ElementElement ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);	//默认的标签解析  根据节点类型不同进行不同操作}else {delegate.parseCustomElement(ele);	//自定义标签的解析和注册}}}}else {delegate.parseCustomElement(root);//自定义标签的解析和注册}}/*** 根据节点类型不同进行不同操作*/private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);	//import节点处理}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);	//alias节点处理}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);	//bean节点处理}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {	//beans节点处理// recursedoRegisterBeanDefinitions(ele);	//回调到doRegisterBeanDefinitions()处理bean节点}}

这里我们看一下bean节点的处理

	/*** bean节点处理*/protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// 注册bean定义BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}/*** 注册bean*/public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();//registry注册器注册BeanDefinitionregistry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// 别名注册String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}

到这里,加载配置,生成bean定义就完成了让我们回到obtainFreshBeanFactory方法的:2.返回刷新后的 BeanFactory

2.getBeanFactory

这里没什么好说的,就是把第一步里创建的beanFactory返回

	/*** 获取beanFactory*/@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {synchronized (this.beanFactoryMonitor) {//加锁if (this.beanFactory == null) {	//判断是否为null 为null则抛出异常throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}return this.beanFactory;	//返回beanFactory}}

 

  相关解决方案