【spring】源码-spring 容器启动过程之beanFactpostProcessBeanFactoryory() 方法(六)

目录

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的注册工作;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东方鲤鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值