关联博文:
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 。
类型 | 相应值 |
---|---|
ApplicationEventPublisher | AnnotationConfigServletWebServerApplicationContext |
ApplicationContext | AnnotationConfigServletWebServerApplicationContext |
BeanFactory | DefaultListableBeanFactory |
ResourceLoader | AnnotationConfigServletWebServerApplicationContext |
HttpSession | WebApplicationContextUtils.SessionObjectFactory |
ServletResponse | WebApplicationContextUtils.ResponseObjectFactory |
ServletRequest | WebApplicationContextUtils.RequestObjectFactory |
WebRequest | WebApplicationContextUtils.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】方法概览
AnnotationConfigServletWebServerApplicationContext
的postProcessBeanFactory
方法。
@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
父类ServletWebServerApplicationContext
的postProcessBeanFactory
方法。
@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方法,这里来到了ServletWebServerApplicationContext
的registerWebApplicationScopes
方法。其首先实例化ExistingWebApplicationScopes ,然后注册web应用会话,最后restore scope。
private void registerWebApplicationScopes() {
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
existingScopes.restore();
}
① WebApplicationContextUtils
我们重点看一下WebApplicationContextUtils
的registerWebApplicationScopes
方法。
//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 。
类型 | 相应值 |
---|---|
ApplicationEventPublisher | AnnotationConfigServletWebServerApplicationContext |
ApplicationContext | AnnotationConfigServletWebServerApplicationContext |
BeanFactory | DefaultListableBeanFactory |
ResourceLoader | AnnotationConfigServletWebServerApplicationContext |
HttpSession | WebApplicationContextUtils.SessionObjectFactory |
ServletResponse | WebApplicationContextUtils.ResponseObjectFactory |
ServletRequest | WebApplicationContextUtils.RequestObjectFactory |
WebRequest | WebApplicationContextUtils.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);
});
}
}
如上所以ExistingWebApplicationScopes
是ServletWebServerApplicationContext
的静态内部类。所以其才可以直接 new ExistingWebApplicationScopes(getBeanFactory());
实例化。
其内部维护了scopes ,保存了request、session域对象(如果存在的话),然后重新放到beanFactory的scopes中。本文这里ExistingWebApplicationScopes
的scopes 为空,不进入方法体。