Spring5源码之五——refresh方法之postProcessBeanFactory()

        书接前文:Spring5源码之四——refresh方法之prepareBeanFactory(),接下来解读一下postProcessBeanFactory()方法。 

        (1)该方法由AbstractRefreshableWebApplicationContext实现。

//注册请求/会话范围、 ServletContextAwareProcessor等
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource { 

    //省略其他代码......

   @Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
	}
}

(2)在(1)中的addBeanPostProcessor()方法,调用到AbstractBeanFactory类的addBeanPostProcessor()方法。该方法主要是提供给想要实现BeanPostProcessor的第三方框架使用,做一些定制化改造。

	@Override
    //添加bean的后置处理器
	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
	
		this.beanPostProcessors.remove(beanPostProcessor);
	
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
		
		this.beanPostProcessors.add(beanPostProcessor);
	}

(3)在(1)中ignoreDependencyInterface(ServletContextAware.class)和ignoreDependencyInterface(ServletConfigAware.class)的目的是在自动注入时忽略指定的依赖接口。

    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
	beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

(4)在(1)中registerWebApplicationScopes(beanFactory, this.servletContext)方法,调用到WebApplicationContextUtils类的registerWebApplicationScopes()方法。其主要目的是使用 WebApplicationContext 使用的给定 BeanFactory 注册特定于 Web 的范围(“request”、“session”、“globalSession”、“application”)。

    public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
			@Nullable ServletContext sc) {

		beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
		beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
		if (sc != null) {
			ServletContextScope appScope = new ServletContextScope(sc);
			beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
			// Register as ServletContext attribute, for ContextCleanupListener to detect it.
			sc.setAttribute(ServletContextScope.class.getName(), appScope);
		}

		beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
		beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
		beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
		beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
		if (jsfPresent) {
			FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
		}
	}

(5)在(1)中registerEnvironmentBeans()方法,调用到WebApplicationContextUtils类的registerEnvironmentBeans()方法,该方法中WebApplicationContext 使用的给定 BeanFactory 注册特定于 Web 的环境 bean(“contextParameters”、“contextAttributes”)。

	public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf,
			@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {

		if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
			bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
		}

		if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
			bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
		}

		if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
			Map<String, String> parameterMap = new HashMap<>();
			if (servletContext != null) {
				Enumeration<?> paramNameEnum = servletContext.getInitParameterNames();
				while (paramNameEnum.hasMoreElements()) {
					String paramName = (String) paramNameEnum.nextElement();
					parameterMap.put(paramName, servletContext.getInitParameter(paramName));
				}
			}
			if (servletConfig != null) {
				Enumeration<?> paramNameEnum = servletConfig.getInitParameterNames();
				while (paramNameEnum.hasMoreElements()) {
					String paramName = (String) paramNameEnum.nextElement();
					parameterMap.put(paramName, servletConfig.getInitParameter(paramName));
				}
			}
			bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
					Collections.unmodifiableMap(parameterMap));
		}

		if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
			Map<String, Object> attributeMap = new HashMap<>();
			if (servletContext != null) {
				Enumeration<?> attrNameEnum = servletContext.getAttributeNames();
				while (attrNameEnum.hasMoreElements()) {
					String attrName = (String) attrNameEnum.nextElement();
					attributeMap.put(attrName, servletContext.getAttribute(attrName));
				}
			}
			bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
					Collections.unmodifiableMap(attributeMap));
		}
	}

(6)看一下(5)中registerSingleton的具体实现。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    //省略部分代码......

    @Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        //调用DefaultSingletonBeanRegistry父类方法
		super.registerSingleton(beanName, singletonObject);
		updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
		clearByTypeCache();
	}

    //更新工厂的内部手动单例名称集
    private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				if (condition.test(this.manualSingletonNames)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					action.accept(updatedSingletons);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// Still in startup registration phase
			if (condition.test(this.manualSingletonNames)) {
				action.accept(this.manualSingletonNames);
			}
		}
	}

    //删除有关按类型映射的任何缓存
    private void clearByTypeCache() {
		this.allBeanNamesByType.clear();
		this.singletonBeanNamesByType.clear();
	}
}

//------------------------------------------------------------------------------------
//------------------------------DefaultSingletonBeanRegistry类------------------------
//------------------------------------------------------------------------------------
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    @Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
			addSingleton(beanName, singletonObject);
		}
	}
}

        至此,postProcessBeanFactory()方法基本分析完毕,spring后续源码未完待续。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`refresh()` 是 Spring 框架中的一个方法,它用于刷新应用程序上下文(ApplicationContext)以更新其内部状态。在 Spring 框架中,`refresh()` 方法是非常重要的,因为它负责完成应用程序上下文的初始化和配置,并准备好所有的单例 bean 以供使用。 下面是 `refresh()` 方法的主要流程: 1. 准备刷新过程中需要用到的变量和标志位; 2. 调用 `prepareRefresh()` 方法,进行一些预处理工作; 3. 调用 `obtainFreshBeanFactory()` 方法,创建 BeanFactory 并进行一些初始化工作; 4. 调用 `prepareBeanFactory(beanFactory)` 方法,对 BeanFactory 进行一些后续处理; 5. 调用 `postProcessBeanFactory(beanFactory)` 方法,对 BeanFactory 进行后置处理; 6. 调用 `invokeBeanFactoryPostProcessors(beanFactory)` 方法,执行 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法; 7. 调用 `registerBeanPostProcessors(beanFactory)` 方法,注册 BeanPostProcessor 实例; 8. 调用 `initMessageSource()` 方法,初始化 MessageSource 组件; 9. 调用 `initApplicationEventMulticaster()` 方法,初始化 ApplicationEventMulticaster 组件; 10. 调用 `onRefresh()` 方法,进行一些自定义的刷新工作; 11. 调用 `registerListeners()` 方法,注册事件监听器; 12. 调用 `finishBeanFactoryInitialization(beanFactory)` 方法,完成所有非延迟初始化的单例 bean 的初始化工作; 13. 调用 `finishRefresh()` 方法,完成上下文的刷新工作。 需要注意的是,`refresh()` 方法在执行过程中会涉及到很多细节,比如如何处理环境变量、如何处理自定义的 bean 定义、如何处理多个上下文之间的关系等等。如果需要深入了解 `refresh()` 方法的实现细节,可以查看 Spring 框架的源代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鹏爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值