Spring中refresh分析之postProcessBeanFactory方法详解

关联博文:
AbstractApplicationContext中refresh方法详解
Spring中refresh分析之prepareRefresh方法详解
Spring中refresh分析之obtainFreshBeanFactory方法详解
Spring中refresh分析之prepareBeanFactory方法详解
Spring中refresh分析之postProcessBeanFactory方法详解
Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解
Spring中refresh分析之registerBeanPostProcessors方法详解
Spring中refresh分析之initMessageSource方法详解
Spring中refresh分析之initApplicationEventMulticaster方法详解
Spring中refresh分析之onRefresh方法详解
Spring中refresh分析之registerListeners方法详解
Spring中refresh分析之finishBeanFactoryInitialization方法详解
Spring中refresh分析之finishRefresh方法详解

接上文Spring中refresh分析之prepareBeanFactory方法详解我们分析过prepareBeanFactory方法后,本文分析postProcessBeanFactory方法。

方法功能总结:

  • 注册Bean后置处理器WebApplicationContextServletContextAwareProcessor
  • 将ServletContextAware放到ignoredDependencyInterfaces中
  • registerScope,如request-RequestScope,session–SessionScope
  • registerScope当servletcontext不为null时注册application–ServletContextScope
  • ServletRequest.class, new RequestObjectFactory())ServletResponse.class, new ResponseObjectFactory()HttpSession.class, new SessionObjectFactory()WebRequest.class, new WebRequestObjectFactory()放入resolvableDependencies
  • 如果有扫描包 交给ClassPathBeanDefinitionScanner完成BeanDefinition加载
  • 如果有注解类 交给AnnotatedBeanDefinitionReader完成BeanDefinition加载

如下所示是方法执行后我们 DefaultListableBeanFactory中的resolvableDependencies 。

类型相应值
ApplicationEventPublisherAnnotationConfigServletWebServerApplicationContext
ApplicationContextAnnotationConfigServletWebServerApplicationContext
BeanFactoryDefaultListableBeanFactory
ResourceLoaderAnnotationConfigServletWebServerApplicationContext
HttpSessionWebApplicationContextUtils.SessionObjectFactory
ServletResponseWebApplicationContextUtils.ResponseObjectFactory
ServletRequestWebApplicationContextUtils.RequestObjectFactory
WebRequestWebApplicationContextUtils.WebRequestObjectFactory

ignoredDependencyInterfaces 则如下所示:

ignoredDependencyInterfaces = {HashSet@4716}  size = 10
"interface org.springframework.context.EnvironmentAware"
"interface org.springframework.context.ApplicationContextAware"
"interface org.springframework.beans.factory.BeanNameAware"
"interface org.springframework.beans.factory.BeanFactoryAware"
"interface org.springframework.context.EmbeddedValueResolverAware"
"interface org.springframework.context.ApplicationEventPublisherAware"
"interface org.springframework.web.context.ServletContextAware"
"interface org.springframework.context.ResourceLoaderAware"
"interface org.springframework.beans.factory.BeanClassLoaderAware"
"interface org.springframework.context.MessageSourceAware"

【1】方法概览

AnnotationConfigServletWebServerApplicationContextpostProcessBeanFactory方法。

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 调用父类的postProcessBeanFactory
	super.postProcessBeanFactory(beanFactory);
	
	//如果有扫描包 交给ClassPathBeanDefinitionScanner完成BeanDefinition定位、加载、注册
	if (this.basePackages != null && this.basePackages.length > 0) {
		this.scanner.scan(this.basePackages);
	}
	// 如果有注解类 交给AnnotatedBeanDefinitionReader完成BeanDefinition注册
	if (!this.annotatedClasses.isEmpty()) {
		this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
	}
}

该方法首先调用父类 postProcessBeanFactory方法,然后通过scanner扫描basePackages完成BeanDefinition定位和加载及注册,使用AnnotatedBeanDefinitionReader完成BeanDefinition注册。

本文这里basePackages和annotatedClasses都为空。

【2】super.postProcessBeanFactory

父类ServletWebServerApplicationContextpostProcessBeanFactory方法。

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

//注册Bean后置处理器WebApplicationContextServletContextAwareProcessor
	beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));

// 放到Set<Class<?>> ignoredDependencyInterfaces中
	beanFactory.ignoreDependencyInterface(ServletContextAware.class);

//注册scope
	registerWebApplicationScopes();
}

如上所示首先注册WebApplicationContextServletContextAwareProcessor到bean后置处理器集合中,其次将ServletContextAware添加到Set<Class<?>> ignoredDependencyInterfaces中,最后向给定的BeanFactory注册特定于web的作用域(“request”、“session”、“globalSession”)。

放到ignoredDependencyInterfaces中的可以理解为这些类将不会通过Autowired自动注入而是会被BeanFactory通过比BeanFactoryAware或者ApplicationContext通过ApplicationContextAware这种方式设置。

WebApplicationContextServletContextAwareProcessor

如下所示,其提供了getServletContext和getServletConfig方法用来获取ServletContext 与ServletConfig 。

public class WebApplicationContextServletContextAwareProcessor extends ServletContextAwareProcessor {

	private final ConfigurableWebApplicationContext webApplicationContext;

	public WebApplicationContextServletContextAwareProcessor(ConfigurableWebApplicationContext webApplicationContext) {
		Assert.notNull(webApplicationContext, "WebApplicationContext must not be null");
		this.webApplicationContext = webApplicationContext;
	}

	@Override
	protected ServletContext getServletContext() {
		ServletContext servletContext = this.webApplicationContext.getServletContext();
		return (servletContext != null) ? servletContext : super.getServletContext();
	}

	@Override
	protected ServletConfig getServletConfig() {
		ServletConfig servletConfig = this.webApplicationContext.getServletConfig();
		return (servletConfig != null) ? servletConfig : super.getServletConfig();
	}

}

【3】registerWebApplicationScopes

我们继续看registerWebApplicationScopes方法,这里来到了ServletWebServerApplicationContextregisterWebApplicationScopes方法。其首先实例化ExistingWebApplicationScopes ,然后注册web应用会话,最后restore scope。

private void registerWebApplicationScopes() {
	ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
	WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
	existingScopes.restore();
}

① WebApplicationContextUtils

我们重点看一下WebApplicationContextUtilsregisterWebApplicationScopes方法。

//WebApplicationContextUtils
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
	registerWebApplicationScopes(beanFactory, null);
}

public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
		@Nullable ServletContext sc) {
		
		//注册request-RequestScope
	beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
	// 注册session--SessionScope
	beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());

	//本文这里为null
	if (sc != null) {	
		ServletContextScope appScope = new ServletContextScope(sc);
		// 注册application--ServletContextScope 
		beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
		// Register as ServletContext attribute, for ContextCleanupListener to detect it.
		// 作为ServletContext属性
		sc.setAttribute(ServletContextScope.class.getName(), appScope);
	}

//放到Map<Class<?>, Object> resolvableDependencies中
	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);
	}
}

其实就是两大块,注册scope以及registerResolvableDependency。

registerScope

如下所示,当scopeName非singleton、prototype时,放入scopes中(其是一个LinkedHashMap)。

@Override
public void registerScope(String scopeName, Scope scope) {
	Assert.notNull(scopeName, "Scope identifier must not be null");
	Assert.notNull(scope, "Scope must not be null");
	if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
		throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
	}
	Scope previous = this.scopes.put(scopeName, scope);
	//...日志打印
}

③ registerResolvableDependency

registerResolvableDependency这里说明一下是什么意思呢?

如下所示在DefaultListableBeanFactory内维护了一个map resolvableDependencies 用来记录那些可解析的依赖。其key为依赖类型,比如ServletRequest,相对应的值比如RequestObjectFactory用来解析得到发生依赖注入时应用/用户需要的bean实例。

/** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

其核心思想就是你可以完成Autowired自动注入,但是注入的bean实例不是从DefaultListableBeanFactory获取。比如ServletRequest,那么将由RequestObjectFactory获取。

本文这里放入了ServletRequest.class, new RequestObjectFactory())ServletResponse.class, new ResponseObjectFactory()HttpSession.class, new SessionObjectFactory()WebRequest.class, new WebRequestObjectFactory()

如果是JSF环境,还会进行进一步处理。

如下所示是方法执行后我们 DefaultListableBeanFactory中的resolvableDependencies 。

类型相应值
ApplicationEventPublisherAnnotationConfigServletWebServerApplicationContext
ApplicationContextAnnotationConfigServletWebServerApplicationContext
BeanFactoryDefaultListableBeanFactory
ResourceLoaderAnnotationConfigServletWebServerApplicationContext
HttpSessionWebApplicationContextUtils.SessionObjectFactory
ServletResponseWebApplicationContextUtils.ResponseObjectFactory
ServletRequestWebApplicationContextUtils.RequestObjectFactory
WebRequestWebApplicationContextUtils.WebRequestObjectFactory

ignoredDependencyInterfaces 则如下所示:

ignoredDependencyInterfaces = {HashSet@4716}  size = 10
"interface org.springframework.context.EnvironmentAware"
"interface org.springframework.context.ApplicationContextAware"
"interface org.springframework.beans.factory.BeanNameAware"
"interface org.springframework.beans.factory.BeanFactoryAware"
"interface org.springframework.context.EmbeddedValueResolverAware"
"interface org.springframework.context.ApplicationEventPublisherAware"
"interface org.springframework.web.context.ServletContextAware"
"interface org.springframework.context.ResourceLoaderAware"
"interface org.springframework.beans.factory.BeanClassLoaderAware"
"interface org.springframework.context.MessageSourceAware"

④ existingScopes.restore

最后我们再回头看一下ServletWebServerApplicationContext的restore方法。

public static class ExistingWebApplicationScopes {

	private static final Set<String> SCOPES;

// 静态代码块
	static {
	// scopes 中放入request session
		Set<String> scopes = new LinkedHashSet<>();
		scopes.add(WebApplicationContext.SCOPE_REQUEST);
		scopes.add(WebApplicationContext.SCOPE_SESSION);
		SCOPES = Collections.unmodifiableSet(scopes);
	}

	private final ConfigurableListableBeanFactory beanFactory;

	private final Map<String, Scope> scopes = new HashMap<>();

	public ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		for (String scopeName : SCOPES) {
		// 从容器中获取对应的Scope 实例,如果不为null,放入scopes
			Scope scope = beanFactory.getRegisteredScope(scopeName);
			if (scope != null) {
				this.scopes.put(scopeName, scope);
			}
		}
	}

// 补偿机制,把scopes放入beanFactory的scopes中。
	public void restore() {
		this.scopes.forEach((key, value) -> {
			if (logger.isInfoEnabled()) {
				logger.info("Restoring user defined scope " + key);
			}
			this.beanFactory.registerScope(key, value);
		});
	}

}

如上所以ExistingWebApplicationScopesServletWebServerApplicationContext的静态内部类。所以其才可以直接 new ExistingWebApplicationScopes(getBeanFactory());实例化。

其内部维护了scopes ,保存了request、session域对象(如果存在的话),然后重新放到beanFactory的scopes中。本文这里ExistingWebApplicationScopes的scopes 为空,不进入方法体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

流烟默

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

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

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

打赏作者

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

抵扣说明:

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

余额充值