【三】Spring IoC 最全源码详解之 prepareBeanFactory

工欲善其事,必先利其器。

                                      —— 《论语·卫灵公》

    本文将开始介绍refresh()方法。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();        
	register(annotatedClasses);
        //本节分析的步骤
	refresh();
}

refresh()方法去掉catch块后的代码如下:

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 为刷新容器前做准备,没什么干货,略过。
		prepareRefresh();

		// 简单理解为获得bean工厂DefaultListableBeanFactory对象即可。
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 为bean工厂加装一些设备,使其在后续繁杂的bean制造过程中能游刃有余
		prepareBeanFactory(beanFactory);

		try {
			// 空壳方法,为以后Spring扩展预留,略过
			postProcessBeanFactory(beanFactory);

			// 对BeanFactoryPostProcessor的注册和回调方法执行
			invokeBeanFactoryPostProcessors(beanFactory);

			// 注册bean的后置处理器,使得bean工厂可以干预bean的实例化过程
			registerBeanPostProcessors(beanFactory);

			// 国际化(略过)
			initMessageSource();

			// 初始化Application事件的广播器
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// 注册事件监听器
			registerListeners();

			// 完成non-lazy bean的实例化
			finishBeanFactoryInitialization(beanFactory);

			// 发布事件和完成扫尾工作
			finishRefresh();
		}
		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

        前面1-2步很简单,我们直接从第3步prepareBeanFactory开始分析。


beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        上述过程中,StandardBeanExpressionResolver对象用于解析形如 #{...}的这种Spring表达式语言SpEL。ResourceEditorRegistrar用于注册用户自定义的PropertyEditor实现类,PropertyEditor实现类用于将外部设置值转换为bean的属性值。


beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        手动添加一个ApplicationContextAwareProcessor的实例化对象到bean后置处理器链表List<BeanPostProcessor> beanPostProcessors中。ApplicationContextAwareProcessor的作用是自动注册以下几个aware类到bean工厂中。

org.springframework.context.EnvironmentAware
org.springframework.context.EmbeddedValueResolverAware
org.springframework.context.ResourceLoaderAware
org.springframework.context.ApplicationEventPublisherAware
org.springframework.context.MessageSourceAware
org.springframework.context.ApplicationContextAware

        随后通过ignoreDependencyInterface(xxx.class)方法忽略给定接口的自动装配功能。官方注释是

忽略给定依赖项接口的自动装配功能。application context通常使用它来注册以其他方式解析的依赖项,如通过BeanFactoryAware解析的BeanFactory或通过ApplicationContextAware解析的ApplicationContext。

        这里有一个疑问:注册ApplicationContextAwareProcessor的作用是实例化上述6个aware类对象到bean工厂,为什么又要通过ignoreDependencyInterface接口忽略掉这6个aware类对象的自动装配呢?(待解决)


beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        接下来是注册几个特殊的依赖解析器,这些解析器是为bean工厂或者说是Spring容器服务的。这几个bean有自动装配(autowired)的能力,但是他们却并不是以bean的形式出现在bean工厂中。简单说来这几玩意是由Spring自行管理的内部对象。


beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

ApplicationListenerDetector通过postProcessAfterInitialization方法,从注册到bean工厂单例bean中所有实现了ApplicationListener接口的bean,放入Spring容器的applicationListeners和applicationEventMulticaster中。


if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
	beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));	
	beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

        Load Time Weaving是再AspectJ在类加载时期进行代码织入的一种技术。如果容器中存在名为"loadTimeWeaver"的bean,则添加一个作用域为loadTimeWeaver的后置处理器。


if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
	beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
	beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}

        假如存在名为enviroment, systemProperties, systemEnviroment的几个bd对象,则将其注册到bean工厂的Map<String, Object> singletonObjects这个ConcurrentHashMap上。也将对应的beanName添加到manualSingletonNames这个List中。

到此,prepareBeanFactory方法就执行完成了。这一步骤为bean工厂空旷的厂房添加了几件常用的设备,后续会经常用到。


如果将00:00-7:00的时刻表映射到Sping的启动流程的话,目前的时间大致应该是在01:30左右。下一节,我们将继续分析refresh方法中的invokeBeanFactoryPostProcessors。这一步骤极为重要。我们下篇文章再见~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值