spring4.x(十)之第六章--spring 高级特性

1. spring 容器

1. 内部工作机制

Spring 的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰地刻画了Spring容器启动时的各项操作
下面是refresh()中的逻辑执行:
这里写图片描述
各步详解:
这里写图片描述
这里写图片描述

下图描述Spring容器从加载配置文件到创建出一个完整Bean的作业流程及参与的角色 :
这里写图片描述
各组件详解:
这里写图片描述
这里写图片描述

注:
1.spring 框架的脉络:

  • 接口层描述了容器的重要组件及组件间的协作关系
  • 继承体系逐步实现组件的各项功能

2.Spring组件按其所承担的角色可以划分为两类 :

  • 物料组件:Resource,BeanDefinition,PropertyEditor及最终的Bean等,像流水线上被加工的物料
  • 设备组件:ResourceLoader,BeanDefinitionReader,BeanFactoryPostProcessor,InstantiationStrategy及BeanWrapper等,像流水线上的加工设备
2. BeanDefinition
  • BeanDefinition是配置文件元素标签在容器内的表示。
  • <bean> 拥有class,scope,lazy-init等配置属性,BeanDefinition对应的有beanClass,scope,lazyInit等属性

这里写图片描述

注: 在配置文件中:

  • <bean> 对应 RootBeanDefinition
  • <bean> 对应 ChildBeanDefinition
  • AbstractBeanDefinition 对二者共同的类信息进行抽象

其中:

  • Spring通过 BeanDefinition 将配置文件中的 <bean> 配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegistry中。
  • BeanDefinitionRegistry就像Spring配置信息的内存数据库,后续操作直接从BeanDefinitionRegistry中读取配置信息。
  • 一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化。

创建最终的BeanDefinition主要包括两个步骤 :

  • ①. 利用BeanDefinitionReader读取承载配置信息的Resource,通过XML解析器解析配置信息的DOM(Document Object Model)对象,简单地为每个生成对应的BeanDefinition。在配置文件中,可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还未被解析出来
  • ②. 利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值
3. InstantiationStrategy
  • InstantiationStrategy负责根据BeanDefinition对象创建一个Bean实例。
  • Spring将实例化Bean的工作通过一个策略接口进行描述,是为了可以方便地采用不同的实例化策略,以满足不同需求。

这里写图片描述

  • SimpleInstantiationStrategy 是最常用的实例化策略,该策略利用Bean实现类的默认构造函数,带参构造函数或工厂方法创建Bean的实例
  • CglibSubclassingInstantiationStrategy 扩展了SimpleInstantiationStrategy,为需要进行方法注入的Bean提供了支持。利用CGLib类库为Bean动态生成子类,在子类中生成方法注入的逻辑,然后使用这个动态生成的子类创建Bean的实例
  • InstantiationStrategy 仅负责实例化Bean的操作,相当于new的功能,不会参数Bean属性的设置。所以由InstantiationStrategy返回的Bean实例,实际上是半成品,属性填充的工作留待BeanWrapper来完成
4. BeanWrapper
  • Spring委托BeanWrapper完成Bean属性的填充工作
  • 在Bean实例被InstantiationStrategy创建出来后容器主控程序将Bean通过BeanWrapper包装起来(通过调用BeanWrapper的setWrappedInstance(Object obj)方法完成)

这里写图片描述

  • PropertyAccessor 接口定义了各种访问Bean 属性的方法
  • PropertyEditorRegistry 是属性编辑器的注册表

BeanWrapper实现类BeanWrapperImpl有三重身份:

  • ①. Bean包装器
  • ②. 属性访问器
  • ③. 属性编辑器注册表

一个BeanWrapperImpl实例内部封装了两类组件:

  • 被封装的待处理的Bean
  • 一套用于设置Bean属性的属性编辑器

填充属性:

  • 目标Bean实例和属性编辑器
  • 获取Bean对应的BeanDefinition,它从BeanDefinitionRegistry中直接获取。Spring主控程序从BeanDefinition中获取Bean属性的配置信息PropertyValue,并使用属性编辑器对PropertyValue进行转换以得到Bean的属性。
  • BeanWrapperImpl在内部使用Spring 的BeanUtils工具类对Bean进行反射操作,设置属性

2. 使用外部属性文件

Spring提供了PropertyPlaceholderConfigurer,它能使Bean在配置时应用外部属性文件。它实现了BeanFactoryPostProcessor接口,也是一个Bean工厂后处理器

1. PropertyPlaceholderConfigurer属性文件
  1. 使用PropertyPlaceholderConfigurer属性文件 :
    这里写图片描述
    通过PropertyPlaceholderConfigurer引入jdbc.properties属性文件,调整数据源Bean的配置:
    这里写图片描述
    或:
    这里写图片描述
  2. PropertyPlaceholderConfigurer的其他属性 : locations,fileEncoding,order,placeholderPrefix和placeholderSuffix
    这里写图片描述
  3. 使用引用属性文件:
    <context:property-placeholder location="classpath:com/smart/placeholder/jdbc.properties"/>
  4. 在基于注解及基于Java类的配置中引用属性:

    • 在基于XML的配置文件中,通过”&{propNaem}”形式引用属性值
    • 在基于注解配置的Bean可以通过@Value注解为Bean的成员变量或方法入参自动注入容器已有的属性
      这里写图片描述
      注:
      1. @Value注解可以为Bean注入一个字面值,亦可以通过@Value(“&{propName}”)的形式根据属性名注入属性值。
      2. 由于标注@Configureration的类本身就相当于标注了@Component,所以标注了@Configuration的类中引用属性的方式和基于注解配置的引用方式是完全一样的

3. 国际化信息

1. Locale

Locale是表示语言和国家/地区信息的本地化类,是创建国际化应用的基础

这里写图片描述

2. 本地化工具类

java.util包中提供了几个支持本地化的格式化操作工具类,如NumberFormat,DateFormat,MessageFormat

如:
这里写图片描述
这里写图片描述
注:

  • pattern1是简单形式的格式化信息串,通过{n}占位符指定动态参数的替换位置索引,{0}表示第一个参数,{1}表示第二个参数,以此类推
  • pattern2,除了参数位置索引索引,还指定了参数的类型和样式。{1,time,short}表示从第二个入参中获取时分秒部分的值,显示为短样式时间;{1,date,long}表示从第二个入参中获取日期部分的值,显示为长样式时间。
  • 在②定义了用于替换格式化占位符的动态参数,用到了自动装包的语法。
  • 在③通过messageFormat的format()方法格式化信息串,使用了系统默认的本地化对象,由于是中文平台,因此默认为Locale.CHINA。在④显示指定了MessageFormat的本地化对象
3. MessageSource

Spring定义了访问国际化信息的MessageSource接口,并定义了几个实现类:
这里写图片描述
这里写图片描述
1.MessageSource类结构 :

这里写图片描述

  • HierarchicalMessageSource接口添加了两个方法,建立父子层级的MessageSource结构,该接口的setParentMessageSource(MessageSource parent)方法用于设置父MessageSource,而
    getParentMessageSource()方法用于返回父MessageSource。
  • HierarchicalMessageSource接口最终的两个实现类是ResourceBundleMessageSource和ReloadableResourceBundleMessageSource。 它们基于ResourceBundle基础类实现,允许仅通过资源吗加载国际化信息。
  • ReloadableResourceBundleMessageSource提供了定时刷新功能,允许在不重启系统的情况更新资源的信息。
  • StaticMessageResource主要用于程序测试,允许通过编程的方式提供国际化信息。而DelegatingMessageSource是为了方便操作父MessageSource而提供的代理类

2.ResourceBundleMessageSource: 该类允许用户通过beanName指定一个资源名(包括类路径的全限定资源名),或通过beanNames指定一组资源名,完成和6-17相同的任务
3.ReloadableResourceBundleMessageSource: 和ResourceBundleMessageSource的唯一区别在于它可以定时刷新资源文件,以便在应用程序不重启的情况下感知资源文件的变化

4. 容器事件

ApplicationContext能发布事件并且允许注册相应的事件监听器,拥有一套完善的事件发布和监听机制。Java通过EventObject类和EventListener接口描述事件和监听器,某个组件或框架如需事件发布和监听机制,需要通过扩展它们进行定义。

在事件体系中,除了事件和监听器外,还有3个重要概念:

  • ①事件源:事件的产生者,任何一个EventObject都必须拥有一个事件源
  • ②事件监听器注册表:组件或框架必须提供事件监听器注册表来保存事件监听器。当组件和框架中的事件源产生事件时,就会通知这些位于事件监听器注册表中的监听器。
  • ③事件广播器:它是事件和事件监听器沟通的桥梁,负责把事件通知给事件监听器

这里写图片描述

1. Spring事件类结构
  1. 事件类:
    这里写图片描述
    注: Application的唯一构造函数是ApplicationEvent(Object source),通过source指定事件源,有两个子类:

    • ApplicationContextEvent:容器事件,拥有4个子类,分别表示容器启动,刷新,停止及关闭的事件
    • RequestHandleEvent:这是一个与Web应用相关的事件,当一个HTTP请求被处理后,产生该事件,只有在web.xml中定义了DispatcherServlet时才会产生该事件。拥有两个子类,分别代表Servlet和Portlet的请求事件
  2. 事件监听器接口 :
    这里写图片描述

    • ApplicationListener接口只定义了一个方法:onApplicationEvent(E event),该方法接收ApplicationEvent事件对象,在该方法中编写事件的响应处理逻辑。
    • SmartApplicationListener定义了两个方法:
      1. boolean supportsEventType(Class<? extends ApplicationEvent> eventType):指定监听器支持哪种类型的容器事件,即它只会对该类型的事件做出响应
      2. boolean supportsSourceType(Class<?> sourceType):指定监听器仅对何种事件源对象做出响应
  3. 事件广播器:
    这里写图片描述

    2. Spring事件体系的具体实现
    • Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了事件体系的搭建。
    • AbstractApplicationContext拥有一个applicationEventMulticaster(应用上下文事件广播器)成员变量,它提供了容器监听器的注册表。

AbstractApplicationContext在refresh()这个容器启动启动方法中通过以下3个步骤搭建了事件的基础设施:
这里写图片描述
注:

  • 在⑤,Spring初始化事件的广播器,可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster即可,Spring会通过反射机制将其注册容器的事件广播器。如果没有找到配置的外部事件广播器,则Spring自动使用SimpleApplicationEventMulticaster作为事件广播器
  • 在⑦,Spring根据反射机制,从BeanDefinitionRegistry中找出所有实现ApplicationListener的Bean,将它们注册为容器的事件监听器,即将其添加到事件广播器所提供的事件监听器注册表中
  • 在⑨,容器启动完成,调用事件发布接口向容器中所有的监听器发布事件

参考: Spring容器高级主题(精通Spring+4.x++企业应用开发实战 五)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值