接上一篇博客:https://blog.csdn.net/qq_43605444/article/details/121996675?spm=1001.2014.3001.5502
16.3 便捷获取底层资源为了优化使用和理解应用程序上下文,您应该熟悉 Spring 的资源抽象,如参考资料中所述。
应用程序上下文是一个 ResourceLoader,可用于加载 Resource 对象。 资源本质上是 JDK java.net.URL 类的功能更丰富的版本。 事实上,Resource 的实现在适当的地方包装了一个 java.net.URL 的实例。 资源可以以透明的方式从几乎任何位置获取低级资源,包括从类路径、文件系统位置、可使用标准 URL 描述的任何位置以及其他一些变体。 如果资源位置字符串是没有任何特殊前缀的简单路径,那么这些资源的来源是特定的并且适合实际的应用程序上下文类型。
您可以将部署到应用程序上下文中的 bean 配置为实现特殊的回调接口 ResourceLoaderAware,以在初始化时自动回调应用程序上下文本身作为 ResourceLoader 传入。 您还可以公开 Resource 类型的属性,用于访问静态资源。 它们像任何其他属性一样被注入其中。 您可以将这些 Resource 属性指定为简单的 String 路径,并在部署 bean 时依赖于从这些文本字符串到实际 Resource 对象的自动转换。
提供给 ApplicationContext 构造函数的位置路径或路径实际上是资源字符串,并且以简单的形式根据特定的上下文实现进行适当处理。 例如 ClassPathXmlApplicationContext 将简单的位置路径视为类路径位置。 您还可以使用带有特殊前缀的位置路径(资源字符串)来强制从类路径或 URL 加载定义,而不管实际的上下文类型。
16.4 应用启动追踪ApplicationContext 管理 Spring 应用程序的生命周期并围绕组件提供丰富的编程模型。 因此,复杂的应用程序可能具有同样复杂的组件图和启动阶段。
使用特定指标跟踪应用程序启动步骤有助于了解启动阶段的时间花在何处,但也可以用作更好地了解整个上下文生命周期的一种方式。
AbstractApplicationContext(及其子类)使用 ApplicationStartup 进行检测,该 ApplicationStartup 收集有关各个启动阶段的 StartupStep 数据:
- 应用程序上下文生命周期(基本包扫描、配置类管理)
- bean 生命周期(实例化、智能初始化、后处理)
- 应用事件处理
这是 AnnotationConfigApplicationContext 中的检测示例:
// create a startup step and start recording StartupStep scanPackages = this.getApplicationStartup().start("spring.context.base-packages.scan"); // add tagging information to the current step scanPackages.tag("packages", () -> Arrays.toString(basePackages)); // perform the actual phase we're instrumenting this.scanner.scan(basePackages); // end the current step scanPackages.end();
应用程序上下文已经通过多个步骤进行了检测。 记录后,可以使用特定工具收集、显示和分析这些启动步骤。 有关现有启动步骤的完整列表,您可以查看专用附录部分。
默认的 ApplicationStartup 实现是一个无 *** 作变体,用于最小化开销。 这意味着默认情况下不会在应用程序启动期间收集任何指标。 Spring framework 附带了一个使用 Java Flight Recorder 跟踪启动步骤的实现:FlightRecorderApplicationStartup。 要使用此变体,您必须在创建后立即将其实例配置到 ApplicationContext。
如果开发人员提供他们自己的 AbstractApplicationContext 子类,或者如果他们希望收集更精确的数据,也可以使用 ApplicationStartup 基础结构。
警告:ApplicationStartup 仅在应用程序启动期间和核心容器中使用; 这绝不是 Java 分析器或 Micrometer 等度量库的替代品。
要开始收集自定义的 StartupStep,组件可以直接从应用程序上下文中获取 ApplicationStartup 实例,使它们的组件实现 ApplicationStartupAware,或者在任何注入点请求 ApplicationStartup 类型。
16.5 方便的 Web 应用程序 ApplicationContext 实例化开发人员在创建自定义启动步骤时不应使用“spring.*”命名空间。 这个命名空间是为内部 Spring 使用保留的,可能会发生变化。
例如,您可以使用 ContextLoader 以声明方式创建 ApplicationContext 实例。 当然,您也可以使用 ApplicationContext 实现之一以编程方式创建 ApplicationContext 实例。
您可以使用 ContextLoaderListener 注册 ApplicationContext,如以下示例所示:
contextConfigLocation /WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml org.springframework.web.context.ContextLoaderListener
侦听器检查 contextConfigLocation 参数。 如果该参数不存在,则侦听器使用 /WEB-INF/applicationContext.xml 作为默认值。 当参数确实存在时,侦听器使用预定义的分隔符(逗号、分号和空格)分隔字符串,并将这些值用作搜索应用程序上下文的位置。 也支持 Ant 风格的路径模式。 示例是 /WEB-INF*Context.xml(对于所有此类 WEB-INF 的任何子目录中的文件)。
16.6 将 Spring ApplicationContext 部署为 Java EE RAR 文件可以将 Spring ApplicationContext 部署为 RAR 文件,将上下文及其所有必需的 bean 类和库 JAR 封装在 Java EE RAR 部署单元中。 这相当于引导独立的 ApplicationContext(仅托管在 Java EE 环境中)能够访问 Java EE 服务器设施。 RAR 部署是部署无头 WAR 文件场景的更自然的替代方案 — 实际上,一个没有任何 HTTP 入口点的 WAR 文件仅用于在 Java EE 环境中引导 Spring ApplicationContext。
RAR 部署非常适合不需要 HTTP 入口点而仅包含消息端点和计划作业的应用程序上下文。 这种上下文中的 Bean 可以使用应用服务器资源,例如 JTA 事务管理器和 JNDI 绑定的 JDBC 数据源实例和 JMS ConnectionFactory 实例,还可以注册到平台的 JMX 服务器 — 全部通过 Spring 的标准事务管理和 JNDI 和 JMX 支持设施。 应用程序组件还可以通过 Spring 的 TaskExecutor 抽象与应用程序服务器的 JCA WorkManager 交互。
有关 RAR 部署中涉及的配置详细信息,请参阅 SpringContextResourceAdapter 类的 javadoc。
将 Spring ApplicationContext 简单部署为 Java EE RAR 文件:
- 将所有应用程序类打包成一个 RAR 文件(这是一个具有不同文件扩展名的标准 JAR 文件)。
- 将所有需要的库 JAR 添加到 RAR 存档的根目录中。
- 添加 meta-INF/ra.xml 部署描述符(如 SpringContextResourceAdapter 的 javadoc 中所示)和相应的 Spring XML bean 定义文件(通常是 meta-INF/applicationContext.xml)。
- 将生成的 RAR 文件放入应用程序服务器的部署目录中。
这种 RAR 部署单元通常是独立的。 它们不会将组件暴露给外部世界,甚至不会暴露给同一应用程序的其他模块。 与基于 RAR 的 ApplicationContext 的交互通常通过它与其他模块共享的 JMS 目标发生。 例如,基于 RAR 的 ApplicationContext 还可以调度一些作业或对文件系统中的新文件做出反应(或类似的)。 如果它需要允许来自外部的同步访问,它可以(例如)导出 RMI 端点,这些端点可能被同一台机器上的其他应用程序模块使用。
17、BeanFactoryBeanFactory API 为 Spring 的 IoC 功能提供了底层基础。 它的具体契约主要用于与 Spring 的其他部分和相关第三方框架的集成,它的 DefaultListableBeanFactory 实现是更高级别的 GenericApplicationContext 容器中的关键委托。
BeanFactory 和相关接口(如 BeanFactoryAware、InitializingBean、DisposableBean)是其他框架组件的重要集成点。 由于不需要任何注解甚至反射,它们允许容器与其组件之间非常有效的交互。 应用程序级 bean 可能使用相同的回调接口,但通常更喜欢声明式依赖注入,或者通过注解或通过编程配置。
请注意,核心 BeanFactory API 级别及其 DefaultListableBeanFactory 实现不会对要使用的配置格式或任何组件注解进行假设。 所有这些风格都通过扩展(例如 XmlBeanDefinitionReader 和 AutowiredAnnotationBeanPostProcessor)进来,并在共享 BeanDefinition 对象上作为核心元数据表示进行 *** 作。 这就是使 Spring 的容器如此灵活和可扩展的本质。
17.1 BeanFactory 还是 ApplicationContext?本节解释 BeanFactory 和 ApplicationContext 容器级别之间的差异以及对引导的影响。
您应该使用 ApplicationContext 除非您有充分的理由不这样做,将 GenericApplicationContext 及其子类 AnnotationConfigApplicationContext 作为自定义引导的常见实现。 这些是用于所有常见目的的 Spring 核心容器的主要入口点:加载配置文件、触发类路径扫描、以编程方式注册 bean 定义和带注释的类,以及(从 5.0 开始)注册功能 bean 定义。
由于 ApplicationContext 包含 BeanFactory 的所有功能,因此通常建议使用普通 BeanFactory,除非需要完全控制 bean 处理的场景。 在 ApplicationContext(例如 GenericApplicationContext 实现)中,根据约定(即通过 bean 名称或 bean 类型 — 特别是后处理器)检测几种 bean,而普通的 DefaultListableBeanFactory 与任何特殊 bean 无关。
对于很多扩展的容器特性,比如注解处理和 AOP 代理,BeanPostProcessor 扩展点是必不可少的。 如果您仅使用普通的 DefaultListableBeanFactory,则默认情况下不会检测和激活此类后处理器。 这种情况可能会令人困惑,因为您的 bean 配置实际上没有任何问题。 相反,在这种情况下,容器需要通过额外的设置来完全引导。
下表列出了 BeanFactory 和 ApplicationContext 接口和实现提供的功能。
要使用 DefaultListableBeanFactory 显式注册 bean 后处理器,您需要以编程方式调用 addBeanPostProcessor,如以下示例所示:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); // populate the factory with bean definitions // now register any needed BeanPostProcessor instances factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor()); factory.addBeanPostProcessor(new MyBeanPostProcessor()); // now start using the factory
要将 BeanFactoryPostProcessor 应用于普通的 DefaultListableBeanFactory,您需要调用其 postProcessBeanFactory 方法,如以下示例所示:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(new FileSystemResource("beans.xml")); // bring in some property values from a Properties file PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer(); cfg.setLocation(new FileSystemResource("jdbc.properties")); // now actually do the replacement cfg.postProcessBeanFactory(factory);
在这两种情况下,显式注册步骤都很不方便,这就是为什么在 Spring 支持的应用程序中,各种 ApplicationContext 变体比普通的 DefaultListableBeanFactory 更受欢迎的原因,尤其是在典型企业设置中依赖 BeanFactoryPostProcessor 和 BeanPostProcessor 实例来扩展容器功能时。
AnnotationConfigApplicationContext 注册了所有常见的注解后处理器,并且可以通过配置注解(例如@EnableTransactionManagement)在幕后引入其他处理器。 在 Spring 基于注解的配置模型的抽象层,bean 后处理器的概念变成了一个纯粹的容器内部细节。
文章参考:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#context-introduction
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)