Xml格式的应用启动3

第3步:prepareBeanFactory(beanFactory),为该Context中持有的beanFactory实例做一些准备工作。

该方法的实现都在AbstractApplicationContext中,逻辑很清晰,我们一步一步分析它做了什么。

第一段

// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

setBeanClassLoader:设置加载Bean用哪个ClassLoader。

setBeanExpressionResolver:设置用来解析BeanDefinition中“EL表达式”的解析器,即写的那些形如#{...}的Spring EL表达式。

addPropertyEditorRegistrar:设置属性编辑器,相当于registerCustomEditor的便捷操作,具体看到底做了什么:

public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {
    this.resourceLoader = resourceLoader;
    this.propertyResolver = propertyResolver;
}

由于AbstractApplicationContext继承自DefaultResourceLoader,而Environment的真正propertyResolve的功能是在PropertySourcesPropertyResolver中,所以这里的resourceLoader是DefaultResourceLoader,而propertyResolver是PropertySourcesPropertyResolver。

第二段

// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

beanFactory.addBeanPostProcessor:添加了一个ApplicationContextAwareProcessor,对于BeanFactory添加的BeanPostProcessor,BeanFactory生产的每个Bean都会在对应的时机回调这个BeanPostProcessor。这个ApplicationContextAwareProcessor是在Bean完成初始化之后执行的,负责回调Bean实现的一些Aware接口方法。

beanFactory.ignoreDependencyInterface(Class<?> ifc):告诉beanFactory,如果某个Bean要自动注入某个Bean时,如果要注入的这个Bean的Class类型为ifc,则不进行注入,这个方法仅在允许在Spring内部中使用,这么做有什么意义呢?TODO,等到后面看什么时候使用了这个属性。

第三段

beanFactory.registerResolvableDependency(dependencyType, autowiredValue)表示:当程序中需要某个dependencyType,给用定的这个autowiredValue来装配,主要是针对那些需要被装配但又没有注册的Bean,这类Bean主要就是beanFactory或者context中的引用,如上所示。

第四段

ApplicationListenerDetector实现了DestructionAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor,在postProcessMergedBeanDefinition中它会记录bean是不是单例,然后在postProcessAfterInitialization中先判断bean是不是ApplicationListener,如果是则再判断是不是单例,如果是单例就将其添加到该context中,所以它的功能就如同它的名字一样:探测应用监听器。

beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)是判断beanFactory是否包含LoadTimeWeaver。在AOP中,织入切面的时机有:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。这个LoadTimeWeaver则是在类加载期间的织入,如果设置了织入器,则需要将beanFactory的类加载器由默认的替换为这个ContextTypeMatchClassLoader这个特殊的类加载器。一般我们都会使用JDK动态代理或者Cglib这种运行期织入的方式,所以这里不再赘述。

第五段

由于是第一次refresh,所以这些if判断都是true,即将这3个bean添加到beanFactory。environment即为第一步创建的StandardEnvironment,systemProperties是系统属性,结构是Map<String, Object>,比如os.version、user.name、java.version等等信息,而systemEnvironment则是系统的环境变量,,结构也是Map<String, Object>,如JAVA_HOME等等。

总结这一步的工作:

①设置beanFactory加载Bean的ClassLoader;

②创建Spring EL表达式的解析器StandardBeanExpressionResolver;

③设置beanFactory的资源加载器DefaultResourceLoader,设置beanFactory的属性解析器PropertySourcesPropertyResolver;

④创建进行Aware接口回调的BeanPostProcessor(ApplicationContextAwareProcessor),并添加到beanFactory中;

⑤加载系统属性和系统变量到beanFactory,并将Environment、systemProperties、systemEnvironment注册到beanFactory。

参考

Spring之LoadTimeWeaver——一个需求引发的思考

Last updated