目录
beanFactpostProcessBeanFactoryory()方法
WebApplicationContextUtils . registerWebApplicationScopes 方法
WebApplicationContextUtils . registerEnvironmentBeans 方法
beanFactpostProcessBeanFactoryory()方法
beanFactory 经过前面 标准的初始化之后,在这里 可以 更改 应用上下文 的 内置 bean 工厂的配置,针对不同 的 ApplicationContext 实现类的配置修改;以及容器内置bean的注册;
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
postProcessBeanFactory 方法 是个抽象模板方法,由不同子类重写实现功能,这里调用的是 AbstractRefreshableWebApplicationContext 类中的实现:
/**
* Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
*/
@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);
}东方鲤鱼
解析:为容器指定事件处理器,涉及类如下
ServletContextAwareProcessor :BeanPostProcessor 的实现类,使用 ServletConfig 或者 ServletContext 类构造的 类;
ServletContextAware : 实现该接口的类 希望 得到 ServletContext 的通知 ,即可以实时获取 ServletContext;
ServletConfigAware:实现该接口的类 希望 得到 ServletConfig的通知 ,即可以实时获取 ServletConfig;
WebApplicationContextUtils . registerWebApplicationScopes():注册 请求域,session 域,应用域 以及 bean 工厂注册 resolvableDependencies,即配置 beanFactory 的 LinkedHashMap 类型的 scopes 的属性值;
WebApplicationContextUtils . registerWebApplicationScopes 方法
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
@Nullable ServletContext sc) {
// 保存作用域名称与实例保存到容器的scopes 集合中
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);
}
// 指定容器注入的对象,防止以为不同时期自动注入引起的异常
//registerResolvableDependency 该方法的主要作用就是指定该类型接口,如果外部要注入该类型接口的对象,则会注入我们指定的对象,而不会去管其他接口实现类
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);
}
}东方鲤鱼
解析:scopes 内部是一个linkedKashMap()对象,而 registerWebApplicationScopes方法最终内部是一个16 大小的ConcurrentHashMap;
registerResolvableDependency方法是指定该类型接口,如果外部要注入该类型接口的对象,则会注入我们指定的对象,而不会去管其他接口实现类;如果要自定义,可以实现BeanFactoryPostProcessor 接口来指定;
WebApplicationContextUtils . registerEnvironmentBeans 方法
public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf,
@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
//注册单例servletContext 对象
if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
}
//注册单例servletConfig 对象
if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
}
//注册单例contextParameters 对象
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));
}
//注册单例contextAttributes 对象
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));
}
}东方鲤鱼
解析:此方法就是将启动时加载到的单例的对注册到容器中,registerSingleton()方法实现单例注册,有两个实现类,DefaultSingletonBeanRegistry,子类DefaultListableBeanFactory;
DefaultSingletonBeanRegistry 实现如下:
@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);
}
}
解析:使用了synchronized 关键字同步代码,现在单例对象池中查询一次,如果存在就抛出异常,如果不存在,则添加进去;
DefaultListableBeanFactory 实现如下:
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
if (!this.beanDefinitionMap.containsKey(beanName)) {
this.manualSingletonNames.add(beanName);
}
}
clearByTypeCache();
}
解析:显然,这个子类先调用了父类的registerSingleton 方法,实现单例注册,然后重写扩展了功能,先判断容器是否启动完成,如果正处于启动阶段,就会对beanDefinitionMap 资源加锁,保证线程安全,然后把要注册的bean 保存到一个新的集合中,然后赋值给全局共享集合,负责也是先判断,后添加;
最后清空allBeanNamesByType与singletonBeanNamesByType两个集合;
整个postProcessBeanFactory 方法就是在处理容器内部bean的注册工作;