org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String)
org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String[], boolean, org.springframework.context.ApplicationContext)
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException { /**
* 调用父类构造, 初始了一些对象和字段属性, 例如:
* 1. 当前 context 的属性初始化:
* - 存储BeanFactoryPostProcessor(BFPP)的集合 {@link org.springframework.context.support.AbstractApplicationContext#beanFactoryPostProcessors}
* - id 容器ID, displayName 容器名称, closed, active 容器关闭启动 活动的 AtomicBoolean标识符 ; {@link org.springframework.context.support.AbstractApplicationContext#id}
* - startupShutdownMonitor 容器锁对象, 在容器'刷新'和'销毁'时需要锁住(同步)的 {@link AbstractApplicationContext#startupShutdownMonitor}
* shutdownHook; JVM 的 HOOK {@link AbstractApplicationContext#shutdownHook}
*
* 2. 如果有父容器,则设置父容器,还会合并配置;
* {@link org.springframework.context.support.AbstractApplicationContext#setParent(org.springframework.context.ApplicationContext)}
*
* 3. 创建支持ant风格解析的资源解析器,支持通配符的类似`"classpath*:applicationContext-*.xml"` 这种, 解析容器所需要的 xml, yml, properties 等配置文件; `spring.profiles.active` 的变量 也是由这个解析器进行处理
* 解析容器所需要的 xml, yml, properties 等配置文件; {@link AbstractApplicationContext#AbstractApplicationContext()}
*/
super(parent); /**
* 解析路径, 路径中支持表达式的变量, 例如: 文件名 application-${env}.xml 环境对象里面有env变量会替换之
*/
setConfigLocations(configLocations); if (refresh) {
public void refresh () throws BeansException, IllegalStateException { // 容器刷新, 执行时, 需要锁住 synchronized ( this .startupShutdownMonitor) { //记录容器 启动时间, 步骤 用于分析性能的 (不重要) StartupStep contextRefresh = this .applicationStartup.start( "spring.context.refresh" ); // Prepare this context for refreshing. /** * 一, (ApplicationContext)的预准备工作; * 容器刷新前的准备工作 * 1. 设置容器的一些状态标志符;设置启动时间, 活动标志符; { @link AbstractApplicationContext#prepareRefresh()} * 2. 获取或者创建 Environment 对象; 加载 System.getProperties(); { @see AbstractApplicationContext#environment} * 3. 验证环境是否包含某配置; 手动添加配置. { @link AbstractApplicationContext#initPropertySources()} * 4. 准备存储 事件监听器 和 事件 的集合容器, 默认为空 { @link AbstractApplicationContext#prepareRefresh()}; */ prepareRefresh(); // Tell the subclass to refresh the internal bean factory. /** * 二, 创建 BeanFactory; * 1. 销毁之前的 beanFactory (如果有的话) { @link AbstractRefreshableApplicationContext#refreshBeanFactory()} * 2. 实例化/创建 beanFactory, 这里是实例类是 `DefaultListableBeanFactory` { @link org.springframework.context.support.AbstractRefreshableApplicationContext#createBeanFactory} * 3. 设置 beanFactory 忽略 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware这三个Aware的接口 { @link AbstractAutowireCapableBeanFactory#AbstractAutowireCapableBeanFactory()} * 因为在初始化Bean时, 会直接调用它们(而不是通过通过 BeanPostProcessor扩展的Aware机制调用) { @link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)} * 4. 设置 beanFactory 序列化ID, 名称 { @link AbstractRefreshableApplicationContext#refreshBeanFactory()} * 5. 扩展点, 定制化这个 BeanFactory 例如: 是否允许 BeanDefinition 覆盖; 是否自动处理循环依赖; * 6. 创建(XML解析器/读取器) XmlBeanDefinitionReader, 并初始化; 留下扩展点, 扩展Reader 例如 是否验证xml等 { @link AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)} * 7. 创建相关对象DocumentLoader, BeanDefinitionDocumentReader,BeanDefinitionParserDelegate { @link org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions(org.w3c.dom.Document, org.springframework.core.io.Resource)} * { @link DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions(Element)} * 加载/解析 XML标签/元素/属性等将其封装为 一个个 BeanDefinition 对象 * 8. 将 BeanDefinitions 注册到 registry { @link BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry)} */ ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); /** * 三,(BeanFactory)预准备工作; * { @link AbstractApplicationContext#prepareBeanFactory(ConfigurableListableBeanFactory)} * 1. 为 beanFactory 设置 bean 的类加载器 { @link ConfigurableBeanFactory#setBeanClassLoader(ClassLoader)} * 2. 为 beanFactory 设置 bean 的 StandardBeanExpressionResolver (表达式(Spring EL)解析器) { @link ConfigurableBeanFactory#setBeanExpressionResolver(BeanExpressionResolver)} * 关于 (Spring EL)解析器: StandardBeanExpressionResolver 的设计是组合优于继承, 内部有两个 SpelExpressionParser(真正解析的) SpelParserConfiguration(配置类) * 3. 为 beanFactory 设置 PropertyEditorRegistrar (主要为 Bean 设置属性的管理类){ @link ConfigurableBeanFactory#addPropertyEditorRegistrar(PropertyEditorRegistrar)} * * PropertyEditorRegistrar 这个主要为 Bean 设置属性的管理类, 比如, 日期类型的数据: 可以是特定格式的字符串, 数字, 还可以是时间戳... * * Spring 为 bean 填充属性, 使用 BeanWrapperImpl 包装了一下(装饰模式) * * BeanWrapperImpl 实现了 PropertyEditorRegistry, 可以往里面注册 PropertyEditor, 可以自定义属性的转换, 编辑逻辑 * 4. 给 beanFactory 添加一个 处理Aware的 BeanPostProcessor (ApplicationContextAwareProcessor) 并忽略掉这7个接口的自动注入:{ @link ConfigurableBeanFactory#addBeanPostProcessor(BeanPostProcessor)} * EnvironmentAware.class, EmbeddedValueResolverAware.class, ResourceLoaderAware.class, ApplicationEventPublisherAware.class, MessageSourceAware.class, ApplicationContextAware.class, ApplicationStartupAware.class * 5. 指定内置的 BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext { @link ConfigurableListableBeanFactory#registerResolvableDependency(Class, Object)} * 这几个Bean对象, 自动注入的 Primary * 6. 给 beanFactory 添加一个 BeanPostProcessor (ApplicationListenerDetector)TODO (事件监听相关) * 7. 给 beanFactory 添加一个 BeanPostProcessor(LoadTimeWeaverAwareProcessor) TODO (AOP AspectJ 织入处理相关的) * 8. beanFactory中如果没有以下名称的 bean, 则直接给 BeanFactory 的一级缓存, 注册几个环境对象 Bean { @link SingletonBeanRegistry#registerSingleton(String, Object)} * 名称常量分别是: * org.springframework.context.ConfigurableApplicationContext#ENVIRONMENT_BEAN_NAME * org.springframework.context.ConfigurableApplicationContext#SYSTEM_PROPERTIES_BEAN_NAME * org.springframework.context.ConfigurableApplicationContext#SYSTEM_ENVIRONMENT_BEAN_NAME * org.springframework.context.ConfigurableApplicationContext#APPLICATION_STARTUP_BEAN_NAME * */ // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. /** * 四, beanFactory 已经准备好了, 设计目的是给(Context)子类预留一个扩展点, 在此时这里所有的 Bean 已经被注册了, 尚未实例化任何bean; * BeanPostProcessors * (这里是空实现) */ postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this .applicationStartup.start( "spring.context.beans.post-process" ); // Invoke factory processors registered as beans in the context. /** * 五, 调用 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor * 若是注册的bean definition 实现了这两个接口, 则会调用(getBean)实例化它, 再调用相应的接口方法; * (注意一下 BeanDefinitionRegistryPostProcessor 是继承自 BeanFactoryPostProcessor的) * 总的来说 调用的优先级是: * 1. 调用接口的优先级: * 1. 优先调用(子类) BeanDefinitionRegistryPostProcessor * 2. 再调用(父类) BeanFactoryPostProcessor * 2. 调用添加的方式的优先级: * 1. 优先调用外部入参, 即直接通过{ @link AbstractApplicationContext#addBeanFactoryPostProcessor(org.springframework.beans.factory.config.BeanFactoryPostProcessor)} 代码添加的 * 2. 再调用容器中实现 BeanFactoryPostProcessor 或者 BeanDefinitionRegistryPostProcessor 的 Bean * 见: { @link org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)} * * 值得一提的是: Spring 对于支持 SPEL表达式, 就是通过 `PropertySourcesPlaceholderConfigurer` 这种方式扩展实现的 * { @link org.springframework.context.support.PropertySourcesPlaceholderConfigurer} */ invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. /** * 六, 注册 BeanPostProcessor (BPP)处理器; * * 1. 拿到所有 BeanPostProcessor 类型的 bean * 2. 实例化 BeanPostProcessor * 优先实例化 实现了 PriorityOrdered 接口的, 在实例化其它的(BPP) * 3. 进行分类存到集合 { @link PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)} * * 对 BeanPostProcessor 进行分类存起来, 再调用, 每个集合分别是 * * 1. priorityOrderedPostProcessors //有实现(PriorityOrdered)排序接口的 * * 2. internalPostProcessors //Spring内部的bean, 见: Spring将bean分为三种角色 * * 3. orderedPostProcessorNames //实现 Ordered 接口 * * 4. nonOrderedPostProcessorNames //没有指定顺序, 无序的 * 这有一点, Spring 对 BeanDefinition 分成三种角色: * 1. 用户定义的 业务相关的 Bean Bean (ROLE_APPLICATION) * 2. 较复杂的 (ROLE_SUPPORT) 较复杂的, 支持 AOP、事务等功能的内部实现? (不重要, 不要每一个细节都扣...) * 3. Spring 内置的(ROLE_INFRASTRUCTURE) * * 4. 排序并注册到 beanFactory * 1. 这里按实现(PriorityOrdered)排序接口的、 @Ordered注解的 等排序存起来. 实际调用的顺序 其实就是存起来的顺序 * 2. 另外 BeanPostProcessor 接口粗粒度太大了, Spring 还细分一些子接口: * 1. SmartInstantiationAwareBeanPostProcessor 它提供了更高级的Bean实例化控制方法。主要作用在于允许对Bean的实例化过程进行更精细的控制和定制。 * 2. MergedBeanDefinitionPostProcessor 在合并Bean定义(MergedBeanDefinition)之后但在实例化Bean之前,允许对合并后的Bean定义进行修改、调整或附加元数据。 * 3. DestructionAwareBeanPostProcessor 它允许在Bean被销毁之前(例如,容器关闭或特定作用域的Bean销毁)执行一些操作。 * 等等以上也会存起来 * 3. 最终调用 BPP是在 { @link AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory)} 实例初始化其他Bean调用 */ registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // Initialize message source for this context. /** * 七, 初始化国际化(I18N) 信息源; * 里面很简单: * 1. 如果beanFactory中有名称为 messageSource 的Bean定义 ,就使用这bean作物国际化消息源 * 如果没有则默认使用 org.springframework.context.support.DelegatingMessageSource 并注册到 beanFactory */ initMessageSource(); // Initialize event multicaster for this context. /** * 八, 初始化事件多播器; * 1. 如果 beanFactory 中包含名称为 applicationEventMulticaster 的bean定义, 则使用这个Bean作为事件多播器; * 如果不包含则创建 SimpleApplicationEventMulticaster作为事件多播器; * 2.创建SimpleApplicationEventMulticaster其实就是初始化了一个,用于存放/管理 ApplicationListener 监听器(观察者)的类, 并注册到 beanFactory * 主要是 { @link org.springframework.context.event.AbstractApplicationEventMulticaster#defaultRetriever} 用于存放/管理 各个监听器的(观察者) * { @link org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType) }调用容器发布事件 */ initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. /** * 九, 给子类(Context)留下一个扩展点 * 没什么好说的, 这里是空实现 */ onRefresh(); // Check for listener beans and register them. /** * 十, 向多播器注册监听器; * 1. 向多播器中注册 在context中的监听器(观察者); * 2. 向多播器中注册 在beanFactory中的bean是监听器(ApplicationListener.class)的(观察者) * 3. 广播 this.earlyApplicationEvents 属性中的事件; * 为什么? * 因为有可能 在容器生命周期中调用了当前 `AbstractApplicationContext#publishEvent` 发布事件, 但是多播器没有初始化完成, 所以会将事件存在this.earlyApplicationEvents 中; * 待容器初始化完成后在流程 { @link org.springframework.context.support.AbstractApplicationContext#registerListeners()} 中会发布存在这里面的事件 * (例如: 在 BeanFactoryPostProcessor 的业务逻辑触发容器的广播事件, 这时候多播器都不存在) * @see AbstractApplicationContext#prepareRefresh() */ registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. /** * 十一, 实例化剩下的所有单例bean * * 1. 为 beanFactory 设置类型转换器(ConversionService) 属性填充时会用到 { @link AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory)} * 2. 为 beanFactory 添加变量解析器 (StringValueResolver) * 如果 beanFactory 上下文中不包含 "默认的变量解析器 (类似 PropertySourcesPlaceholderConfigurer) 解析类似 '${}' 这样的变量 " * 则使用环境对象(ConfigurableEnvironment)中的 ConfigurablePropertyResolver实现来作为 StringValueResolver 添加进去 * 3. 冻结配置, 此后就不再允许更改 beanDefinition 了 * 4. 实例化所有剩余的 (非lazy-init) 单例 Bean * 5. 处理 FactoryBean 类型的bean { @link DefaultListableBeanFactory#preInstantiateSingletons()} * 如果该bean是 FactoryBean, 则在 bean name 前面加一个 '&' 前缀, 先获取/实例化 FactoryBean 本身; * (注意一下 FactoryBean 生成对象是不遵循 Spring 的bean生命周期的) * 这有两个对象, 如何获取? getBean(beanName) : * 1. 传入 FactoryBean 的 name 返回的是其 getObject 的目标对象实例; * 2. 如果想获取 FactoryBean 本身实例, 则前面需要加一个 '&' 前缀; * 6. 尝试从当前容器 一 二 三级缓存获取 { @link AbstractBeanFactory#doGetBean(String, Class, Object[], boolean)} * 7. 处理 AOP 代理对象生成 { @link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])} * 8. 在JVM层面实例化对象 { @link AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])} * 1.真正在jvm层面实例化对象; * 1. 如果该 BeanDefinition 有配置 instanceSupplier属性(java.util.function.Supplier), * 将使用其Supplier#get方法的返回, 作为实例对象 * 2. 如果该 BeanDefinition 有配置 factory-method 将使用该方法返回的, 作为实例对象 * 这里这里包括'静态工厂'和'实例工厂'的处理(通过bd的factoryBeanName 进行判断, 如果存在则是'实例工厂') * 3. 使用反射实例化, 根据策略实例化Bean对象 { @link org.springframework.beans.factory.support.SimpleInstantiationStrategy} * - 使用有参构造函数注入,创建 (new) * - 使用无参构造函数创建 (new) * - 工厂方法实例化 ('静态工厂' '实例工厂' ) * `<bean factory-bean="bookFactoryBean" factory-method="getBook()"/>` * 静态工厂: factory-bean 若是 全限定类名 则使用 BookFactoryBean::getBook 的静态方法返回的对象 * 实例工厂: factory-bean 若是 bean 名 则使用该实例方法返回的对象 * 2. 用 BeanWrapper 包装原始bean (装饰模式) * 3. 初始化 BeanWrapper * 1. 给 BeanWrapper 设置了, ConversionService * 2. 给 BeanWrapper 注册了, 当前 bean factory (propertyEditorRegistrars)中的全部 PropertyEditor * 3. 处理 MergedBeanDefinitionPostProcessor 的接口回调 { @link AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors(RootBeanDefinition, Class, String)} * 调用 添加在 context 中 BeanPostProcessor 的 MergedBeanDefinitionPostProcessor 的接口回调 * 解析到诸如` @Autowired`之类的注解 (Metadata)元信息,合并到BeanDefinition中 * 4. 填充Bean属性 { @link AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition, BeanWrapper)} * 1. 如果是AOP, pointcut, advice相关的, synthetic 会配置为 true 调用 BeanPostProcessor 的子接口 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation * (作用是 在实例化之后,属性填充之前执行操作, 可以拦截属性填充操作) * 2. 处理注解的 byName 或者 byType 注入的属性 * 3. 回调所有 InstantiationAwareBeanPostProcessor#postProcessProperties 方法 * 比如, ` @Autowired` 的处理对应实现类: { @link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor} * (作用是: 在工厂将属性值应用到给定bean之前,对它们进行处理) * 注意这里也只是解析, 并没有设置进去, 实际赋值方法见: { @link AbstractAutowireCapableBeanFactory#applyPropertyValues(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.BeanWrapper, org.springframework.beans.PropertyValues)} * 5.初始化Bean对象 { @link AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)} * 1. 先调用这三个 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware { @link AbstractAutowireCapableBeanFactory#invokeAwareMethods(String, Object)} * 这三个是在创建BeanFactory 时忽略的三个 Aware 接口 * 2. 调用所有 BeanPostProcessors#postProcessBeforeInitialization (作用: 在Bean初始化之前调用) { @link AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization(Object, String)} * 3. 调用 init-method 方法 { @link AbstractAutowireCapableBeanFactory#invokeInitMethods(String, Object, RootBeanDefinition)} * 4. 调用所有 BeanPostProcessors#postProcessAfterInitialization (作用: 在Bean初始化之后调用) { @link AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object, String)} * 6. 注册 bean销毁的工作(如果需要){ @link AbstractBeanFactory#registerDisposableBeanIfNecessary(String, Object, RootBeanDefinition)}tcwjzs.com。 * 1. org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(Object,String) BPP接口 * 2. org.springframework.beans.factory.DisposableBean 接口 * 3. 自定义 destroy方法 * (在容器关闭时会调用会按这个顺序调用) * */ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. /** * 十二, 完成容器刷新 * 1. 清理各种缓存资源 * 2. 为当前上下文初始化生命周期处理器 * 3. 发布 ContextRefreshedEvent (Context 完成刷新)事件 */ finishRefresh(); } catch (RuntimeException | Error ex ) { if (logger.isWarnEnabled()) { logger.warn( "Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag.
* Prepare this context for refreshing, setting its startup date and * active flag as well as performing any initialization of property sources. * 容器刷新前的准备工作 * 1. 设置容器的一些状态标志符;设置启动时间, 活动标志符; { @link AbstractApplicationContext#prepareRefresh()} * 2. 获取或者创建 Environment 对象; 加载 System.getProperties(); { @see AbstractApplicationContext#environment} * 3. 验证环境是否包含某配置; 手动添加配置. { @link AbstractApplicationContext#initPropertySources()} * 4. 准备存储 事件监听器 和 事件 的集合容器, 默认为空 { @link AbstractApplicationContext#prepareRefresh()}; */ protected void prepareRefresh () { // 设置容器的一些状态标志符;设置启动时间, 活动标志符; // Switch to active. this .startupDate = System.currentTimeMillis(); this .closed.set( false ); this .active.set( true ); if (logger.isDebugEnabled()) { 1rt.cn, if (logger.isTraceEnabled()) { logger.trace( "Refreshing " + this ); } else { logger.debug( "Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. //留给子类扩展的方法: 验证环境是否包含某配置; 手动添加配置;... initPropertySources(); // Validate that all properties marked as required are resolvable: /** * 验证必须的存在的配置. 例如调用 `setRequiredProperties("iot.config.thread")`之后, 在这里会验证是否存在 iot.config.thread 配置,否则会抛出异常 MissingRequiredPropertiesException * { @link ConfigurablePropertyResolver#setRequiredProperties(String...) } */ getEnvironment().validateRequiredProperties(); // s tore pre-refresh ApplicationListeners... //存储监听器的集合初始化; this.earlyApplicationEvents(刷新前的监听器) if ( this .earlyApplicationListeners == null ) { //如果为空,则添加 this.applicationListeners 在boot中是有值的 this .earlyApplicationListeners = new LinkedHashSet <>( this .applicationListeners); } else { // 如果不为空, 则清空; 注意这是 content 的复用方法 Refresh() // Reset local application listeners to pre-refresh state. this .applicationListeners.clear(); this .applicationListeners.addAll( this .earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this .earlyApplicationEvents = new LinkedHashSet <>();
/** * 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. * { @link org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory} */ protected final void refreshBeanFactory () throws BeansException { // 如果有 则销毁之前的 BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory();529529.cn, } try { /** * <!> 创建 DefaultListableBeanFactory { @link org.springframework.context.support.AbstractRefreshableApplicationContext#createBeanFactory} * 设置 beanFactory 忽略 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware这三个Aware的接口 { @link AbstractAutowireCapableBeanFactory#AbstractAutowireCapableBeanFactory()} * 因为在初始化Bean时, 会直接调用它们(而不是通过通过 BeanPostProcessor扩展的Aware机制调用) { @link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)} */ DefaultListableBeanFactory beanFactory = createBeanFactory(); // 设置 beanFactory 序列化ID beanFactory.setSerializationId(getId()); /** * 定制化 BeanFactory <!> 可扩展点 * { @link org.springframework.context.support.AbstractRefreshableApplicationContext#customizeBeanFactory(org.springframework.beans.factory.support.DefaultListableBeanFactory)} * 1. 是否允许 BeanDefinition 覆盖; 如果不是null,则覆盖默认值, 可以留给子类扩展的 * 2. 是否自动处理循环依赖; 可以留给子类扩展的 */ customizeBeanFactory(beanFactory); /** * 加载 BeanDefinitions <!>重点 { @link AbstractRefreshableApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)} * 1. 创建(XML解析器/读取器) XmlBeanDefinitionReader, 并初始化; 留下扩展点, 扩展Reader 例如 是否验证xml等 * 2. 创建相关对象 DocumentLoader, BeanDefinitionDocumentReader, BeanDefinitionParserDelegate * 加载解析 XML的标签/元素/属性 等并且将其封装为 一个个 BeanDefinition 对象 * 3. 将 BeanDefinitions 注册到 registry */ loadBeanDefinitions(beanFactory); snackman.cn, this .beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException ( "I/O error parsing bean defi
* Create an internal bean factory for this context. * Called for each { @link #refresh()} attempt. * <p>The default implementation creates a * { @link org.springframework.beans.factory.support.DefaultListableBeanFactory} * with the { @linkplain #getInternalParentBeanFactory() internal bean factory} of this * context's parent as parent bean factory. Can be overridden in subclasses, * for example to customize DefaultListableBeanFactory's settings. * @return the bean factory for this context * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping */ protected DefaultListableBeanFactory createBeanFactory () { return new DefaultListableBeanFactory (getInternalParentBeanFactory());
Loads the bean definitions via an XmlBeanDefinitionReader. * * 1. 创建(XML解析器/读取器) XmlBeanDefinitionReader { @link AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)} * - 给 beanDefinitionReader 设置环境对象, 可以让 XmlBeanDefinitionReader 做变量表达式解析比如 ${jdbc.url} * - 给 beanDefinitionReader 设置 BeanFactory * - 给 beanDefinitionReader 设置 要用于解析的SAX实体解析器; (SAX全称 Simple API for XML,既是一种接口,也是一种软件包。它是一种XML解析的替代方法) * 注意这里加载了两个对象: 1. BeansDtdResolver (XSD,DTD解析器); 2. PluggableSchemaResolver 映射(本地文件xsd检验) 'META-INF/spring.schemas'文件信息 * 例如, context 命名空间xml检验的映射: * <code> http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd</code> * @see DelegatingEntityResolver#DelegatingEntityResolver(java.lang.ClassLoader) * { @link AbstractXmlApplicationContext#initBeanDefinitionReader(XmlBeanDefinitionReader)} * 2. 调用扩展点方法, 扩展/定制 XmlBeanDefinitionReader * 3. 加载 BeanDefinitions <!> * * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. /** * 创建(XML解析器/读取器) XmlBeanDefinitionReader { @link AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)} * 注意传过去的 DefaultListableBeanFactory 它实现了 BeanDefinitionRegistry 作为 Registry 传递进去 * 最后解析出来的 BeanDefinition, 使用该 Registry 作为注册中心 */ XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader (beanFactory); // Configure the bean definition reader with this context's // resource loading environment.winered.cn, // 给 beanDefinitionReader 设置环境对象, 可以让 XmlBeanDefinitionReader 做变量表达式解析比如 ${jdbc.url} beanDefinitionReader.setEnvironment(getEnvironment()); // 给 beanDefinitionReader 设置 BeanFactory beanDefinitionReader.setResourceLoader( this ); /** * 给 beanDefinitionReader 设置 要用于解析的SAX实体解析器; (SAX全称 Simple API for XML,既是一种接口,也是一种软件包。它是一种XML解析的替代方法) * 注意这里加载了两个对象: 1. BeansDtdResolver (XSD,DTD解析器); 2. PluggableSchemaResolver 映射(本地文件xsd检验) 'META-INF/spring.schemas'文件信息 sdcnjx.cn, * 例如, context 命名空间xml检验的映射: `http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd` * 使用这两个解析器避免从网络下载DTD或XSD,解析器会根据这些模式定义验证配置文件的结构是否正确。如果验证失败,容器将无法启动 * @see DelegatingEntityResolver#DelegatingEntityResolver(java.lang.ClassLoader) */ beanDefinitionReader.setEntityResolver( new ResourceEntityResolver ( this )); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. /** * 调用扩展点方法, 扩展/定制 XmlBeanDefinitionReader { @link AbstractXmlApplicationContext#initBeanDefinitionReader(XmlBeanDefinitionReader)} */ initBeanDefinitionReader(beanDefinitionReader); /** * 加载 BeanDefinitions, 并注册到 Registry 中, 这个步骤, 为了复用代码嵌套的方法非常多, 总结一下关键点 * 1. 为了代码复用,多个方法重载 配置文件路径 (String参数), 多配置文件(数组参数) , 在统一转为 `org.springframework.core.io.Resource` 对象去迭代 * 最终读取配置文件的输入流在 { @link org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)} * 2.
/** * Create the default implementation of { @link NamespaceHandlerResolver} used if none is specified. * <p>The default implementation returns an instance of { @link DefaultNamespaceHandlerResolver}. * @see DefaultNamespaceHandlerResolver#DefaultNamespaceHandlerResolver(ClassLoader) */ protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver () { ResourceLoader resourceLoader = getResourceLoader(); ClassLoader cl = (resourceLoader != null ? resourceLoader.getClassLoader() : getBeanClassLoader()); // 解析自定义标签的 NamespaceHandlerResolver 命名空间 handle 映射
* Load the bean definitions with the given XmlBeanDefinitionReader. * <p>The lifecycle of the bean factory is handled by the { @link #refreshBeanFactory} * method; hence this method is just supposed to load and/or register bean definitions. * * 根据资源文件数组迭代加载解析 * 加载 Resource[] 形式的配置文件 * 加载 String[] 形式的配置文件 * * @param reader the XmlBeanDefinitionReader to use * @throws BeansException in case of bean registration errors * @throws IOException if the required XML document isn't found * @see #refreshBeanFactory * @see #getConfigLocations * @see #getResources * @see #getResourcePatternResolver */ protected void loadBeanDefinitions (XmlBeanDefinitionReader reader) throws BeansException, IOException { //加载 Resource[] 形式的配置文件 Resource[] configResources = getConfigResources(); xyzdh.cn, if (configResources != null ) { reader.loadBeanDefinitions(configResources); } //加载 String[] 形式的配置文件 String[] configLocations = getConfigLocations(); if (configLocations != null ) { reader.loadBeanDefinitions(configLocations);
* Load bean definitions from the specified resource location. * <p>The location can also be a location pattern, provided that the * ResourceLoader of this bean definition reader is a ResourcePatternResolver. * @param location the resource location, to be loaded with the ResourceLoader * (or ResourcePatternResolver) of this bean definition reader * @param actualResources a Set to be filled with the actual Resource objects * that have been resolved during the loading process. May be { @code null} * to indicate that the caller is not interested in those Resource objects. * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors * @see #getResourceLoader() * @see #loadBeanDefinitions(org.springframework.core.io.Resource) * @see #loadBeanDefinitions(org.springframework.core.io.Resource[]) */ public int loadBeanDefinitions (String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null ) { throw new BeanDefinitionStoreException ( "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available" ); } if (resourceLoader instanceof ResourcePatternResolver resourcePatternResolver) { // Resource pattern matching available. try { /** * 对于变量处理 在 { @link org.springframework.context.support.AbstractRefreshableConfigApplicationContext#setConfigLocations(String...)} 已经处理过一遍了, 这里又处理一遍? * * 这里的重点是: 将 String 路径 转为Resourced对象, 处不处理变量无所谓, 不是重点 * 处理文件名包含变量表达式的, 例如: application-${active}.xml, 用环境对象变量替换之 */ Resource[] resources = resourcePatternResolver.getResources(location); int count = loadBeanDefinitions(resources); if (actualResources != null ) { Collections.addAll(actualResources, resources); } if (logger.isTraceEnabled()) { logger.trace( "Loaded " + count + " bean definitions from location pattern [" + location + "]" ); } return count;yousLab.com, } catch (IOException ex) { throw new BeanDefinitionStoreException ( "Could not resolve bean definition resource pattern [" + location + "]" , ex); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); int count = loadBeanDefinitions(resource); if (actualResources != null ) { actualResources.add(resource); } if (logger.isTraceEnabled()) { logger.trace( "Loaded " + count + " bean definitions from location [" + location + "]" ); } return count;xyxdLsm.com,
/** * 将 Resource 包装为 EncodedResource 加载, 应该主要是解决编码的问题 * Load bean definitions from the specified XML file. * @param resource the resource descriptor for the XML file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ public int loadBeanDefinitions (Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions( new EncodedResource (resource)); firstfeed.com.cn,
* Load bean definitions from the specified XML file. * @param encodedResource the resource descriptor for the XML file, * allowing to specify an encoding to use for parsing the file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ public int loadBeanDefinitions (EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null" ); if (logger.isTraceEnabled()) { logger.trace( "Loading XML bean definitions from " + encodedResource); } //使用Set存储已加载的配置资源 Set<EncodedResource> currentResources = this .resourcesCurrentlyBeingLoaded.get(); // 当遇到循环 import definitions 时抛出异常 7632.com.cn, if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException ( "Detected cyclic loading of " + encodedResource + " - check your import definitions!" ); } // 获得配置文件的输入流; 这里真正的开始读 psnsd.com, try ( InputStream inputStream = encodedResource.getResource().getInputStream()) { InputSource inputSource = new InputSource (inputStream); if (encodedResource.getEncoding() != null ) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } catch (IOException ex) { throw new BeanDefinitionStoreException ( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this .resourcesCurrentlyBeingLoaded.remove();
* Called by { @code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * { @code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions (Document doc, Resource resource) throws BeanDefinitionStoreException { /** * zjtgjx.net, 这里又创建了一个 BeanDefinitionDocumentReader 对象, 用来读取/解析 Document */ BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); /** * 解析并注册 bean definitions 到 Registry 中 * <br /> * 解析XML自定义标签 需要注意一下, 这里的第2个参数创建的 XmlReaderContext; * 它从这里创建了 { @link XmlBeanDefinitionReader#getNamespaceHandlerResolver()} 命名空间处理器解析器, 后续解析到对应的命名空间处理, 调用其 NamespaceHandler#parse 进行解析 * 它默认读取的配置是 `META-INF/spring.handlers` * 例如: * 529529.cn, spring-context 模块的中 `META-INF/spring.handlers` 定义的handles有如下这些 * http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler * http\://,org.springframework.ejb.config.JeeNamespaceHandler zgongfu.cn,* http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler * http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler * http\:// * * spring-aop 模块的中 `META-INF/spring.handlers` 定义的handles有如下这些 * http\:// */ documentReader.registerBeanDefinitions(doc, snackman.cn。createReaderContext(resource)); // 返回解析 bean definitions 的数量 return getRegistry().getBeanDefinitionCount() - countBefore;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048956/viewspace-3109288/ ,如需转载,请注明出处,否则将追究法律责任。