简述
BeanFactory的后置处理,这是一个模板方法,允许子类在BeanFactory创建完成后进行额外的配置。
这是refresh()方法的第4步,在BeanFactory创建完成(obtainFreshBeanFactory)和配置完成(prepareBeanFactory)之后执行。
AbstractApplicationContext提供空实现,具体的ApplicationContext子类可以重写此方法来添加特定的配置。
核心流程
- AbstractApplicationContext提供空实现(模板方法)
- 子类可以重写以添加特定配置
- 例如:Web应用添加request/session作用域
源码分析
AbstractApplicationContext的空实现:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// ... 前面的步骤
// 获取BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 配置BeanFactory的标准特性
prepareBeanFactory(beanFactory);
try {
// 后置处理BeanFactory(模板方法)
postProcessBeanFactory(beanFactory);
// ... 后续步骤
}
catch (BeansException ex) {
// 异常处理
}
}
}
/**
* 模板方法:在标准初始化之后修改ApplicationContext的内部BeanFactory
* 所有Bean定义都已加载,但还没有Bean被实例化
* 允许在某些ApplicationContext实现中注册特殊的BeanPostProcessor等
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 默认空实现,供子类重写
}
}
ServletWebServerApplicationContext的实现
Web应用需要添加Web相关的配置:
public class ServletWebServerApplicationContext extends GenericWebApplicationContext
implements ConfigurableWebServerApplicationContext {
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 1. 添加WebApplicationContextServletContextAwareProcessor
// 用于处理ServletContextAware和ServletConfigAware接口
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
// 2. 忽略ServletContextAware接口的自动装配
// 因为已经由WebApplicationContextServletContextAwareProcessor处理
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
// 3. 注册Web相关的作用域
registerWebApplicationScopes();
}
private void registerWebApplicationScopes() {
// 获取ServletContext
ServletContext servletContext = getServletContext();
if (servletContext != null) {
// 注册request作用域
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST,
new RequestScope());
// 注册session作用域
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION,
new SessionScope());
// 注册application作用域(等同于ServletContext)
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION,
new ServletContextScope(servletContext));
// 注册ServletContext为可解析依赖
beanFactory.registerResolvableDependency(ServletContext.class, servletContext);
}
}
}
GenericWebApplicationContext的实现
更通用的Web应用上下文实现:
public class GenericWebApplicationContext extends GenericApplicationContext
implements ConfigurableWebApplicationContext, ThemeSource {
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 1. 添加ServletContextAwareProcessor
if (this.servletContext != null) {
beanFactory.addBeanPostProcessor(
new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
// 2. 注册Web作用域
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 3. 注册环境Bean
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
this.servletContext, this.servletConfig);
}
}
添加的Web相关作用域
| 作用域 | 说明 | 生命周期 |
|---|---|---|
| request | 请求作用域 | 每个HTTP请求创建一个Bean实例 |
| session | 会话作用域 | 每个HTTP Session创建一个Bean实例 |
| application | 应用作用域 | 整个ServletContext共享一个Bean实例 |
| websocket | WebSocket作用域 | 每个WebSocket会话一个Bean实例 |
使用示例:
@Component
@Scope("request")
public class RequestScopedBean {
// 每个HTTP请求都会创建新实例
}
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopedBean {
// 每个HTTP Session创建新实例
// proxyMode用于在单例Bean中注入会话作用域Bean
}
与prepareBeanFactory的区别
| 方法 | 时机 | 修改范围 | 典型操作 |
|---|---|---|---|
| prepareBeanFactory() | BeanFactory创建后 | 通用配置 | 添加通用BeanPostProcessor、注册依赖 |
| postProcessBeanFactory() | prepareBeanFactory之后 | 子类特定配置 | 添加特定作用域、特定BeanPostProcessor |
prepareBeanFactory是AbstractApplicationContext的标准配置,所有类型的应用都需要。
postProcessBeanFactory是子类的扩展点,不同类型的应用有不同的需求。
常见子类的实现
1. AnnotationConfigApplicationContext
基本不需要额外配置,使用默认空实现。
2. ClassPathXmlApplicationContext
基本不需要额外配置,使用默认空实现。
3. StaticWebApplicationContext(测试用)
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
4. ReactiveWebServerApplicationContext(响应式Web)
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加响应式Web相关配置
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ReactiveAdapterRegistry.class);
}
执行时机说明
在postProcessBeanFactory执行时:
- ✅ BeanFactory已创建
- ✅ BeanFactory已配置(ClassLoader、BeanPostProcessor等)
- ✅ 可以注册额外的BeanPostProcessor
- ✅ 可以注册额外的作用域
- ❌ BeanDefinition还未处理(在下一步invokeBeanFactoryPostProcessors中处理)
- ❌ Bean还未实例化
参考调用栈
postProcessBeanFactory:678, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:530, AbstractApplicationContext (org.springframework.context.support)
refresh:143, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:755, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)