Spring容器刷新之obtainFreshBeanFactory

obtainFreshBeanFactory是容器刷新的第二步,主要是刷新beanfactory,然后返回beanfactory。

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory(); //模版方法,子类实现
		return getBeanFactory();
	}

refreshBeanFactory主要有两种实现,也就是分两种情况

(1)AbstractRefreshableApplicationContext
ClassPathXmlApplicationContext就是这种类型,如果使用XML配置文件生成容器,那么就会走下面的方法

	/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	 //上面的英文注释大概是说执行此方法会关闭已经存在的beanfactory然后重新初始化
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) { //当前存在beanfactory
			destroyBeans(); //销毁所有单例bean
			closeBeanFactory(); //将beanfactory引用置为null
		}
		try {
			//创建DefaultListableBeanFactory,如果有父容器就设置上
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			//设置是否允许bean定义重写和是否允许循环引用
			//子类可以重写这个方法以配置任何DefaultListableBeanFactory的设置
			customizeBeanFactory(beanFactory);
			//加载bean的定义信息(BeanDefinition)到beanfactory中
			//这里会根据容器类型的不同而采用不同方式,但主要还是读取XML配置信息
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory; //保存新的beanfactory
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

(2)GenericApplicationContext
AnnotationConfigApplicationContext是这种类型,如果使用注解配置类生成容器,就会走下面的方法

	/**
	 * Do nothing: We hold a single internal BeanFactory and rely on callers
	 * to register beans through our public methods (or the BeanFactory's).
	 * @see #registerBeanDefinition
	 */
	 //上面英文注释是说,此类持有一个BeanFactory,并且依赖其他地方调用registerBeanDefinition方法注册bean的定义信息,因此在这什么都不用做
	 //GenericApplicationContext在构造器调用时要么传入一个DefaultListableBeanFactory,要么会new一个
	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

源码大体上看完,简单总结一下:
XML配置和注解配置产生的容器是不同的,主要的不同在于是否会在这一步加载BeanDefinition。XML配置的会在此时加载,而注解配置的不会。那么,注解配置的容器在何时加载BeanDefinition呢?

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * @param componentClasses one or more component classes — for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

很显然,在容器refresh()之前就已经注册了(这里注册的是主配置类,@Bean标注的方法所对应的bean定义信息是在invokeBeanFactoryPostProcessors时被扫描进容器的)。而基于XML配置的容器在构造器中只是设置了配置文件的位置。

最后只要将beanfactory返回就可以了,容器刷新第二步完成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值