Spring5.3学习——from 官网 day1-1

news/2024/5/14 23:47:10/文章来源:https://blog.csdn.net/qq_51553982/article/details/126921507

Spring5.3学习——from 官网day1-1

  • Spring5.3学习——from 官网day1-1
    • 前言
    • 概述
    • Spring的设计理念
    • Spring核心:IOC
      • 什么是IOC
        • 解释
      • IOC容器的包
      • 什么是Bean
    • BeanFactory接口简述
    • ApplicationContext接口简述
    • BeanFactory源码
      • 描述
        • 以下是Bean工厂创建和销毁bean的完整生命周期流程
      • 常量`&`
      • 获取Bean实例
        • 通过Bean的名字获取bean
        • 通过Bean名字获取bean并预设返回Bean的类型
        • 通过Bean名字获取bean并通过传入参数进行显示构造
        • 通过Bean的类型获取Bean实例
        • 通过Bean名字获取bean并通过类型约束传入参数进行显示构造
      • 获取Bean的提供者
        • 通过传入Bean的类型获取Bean的提供者
        • 通过ResolvableType对Bean类型进行规范
      • 判断bean工厂中是否含有指定Bean
      • 判断Bean为单例或多例
        • 判断Bean是否为单例Bean
        • 判断Bean是否为多例Bean
      • 判断类型是否匹配
      • 获取Bean的类型
      • 返回给定 bean 名称的别名
      • 简单示例
        • TestBean
        • 测试
    • ApplicationContext扩展说明
      • MessageSource源码及说明
        • 获取消息并进行国际化
      • 示例
        • 1.编写properties设置映射关系
          • messages_en.properties
          • messages_zh.properties
        • 2.编写国际化信息转换
      • ResourceLoader源码及说明
        • 常量
        • ResourceUtils源码及说明
          • 常量
          • 判断给定的资源是否为URL
          • 获取文件
          • 判断给定的路径是否为文件路径
          • 判断是否为jar包路径
          • 判断是否指定jar包本身的路径
          • 从给定的 URL 中提取实际 jar 文件的 URL
          • 为给定的位置字符串创建一个 URI 实例,首先用“%20”URI 编码替换空格
          • 设定使用缓存标志
        • 返回指定资源位置的Resource句柄
        • 获取类加载器
      • ResourcePatternResolver源码及说明
        • 常量
        • 根据传入目标资源地址获取资源
        • 示例:获取资源
      • EnvironmentCapable源码及说明
        • 获取当前环境
        • 示例:获取当前环境参数
      • ApplicationEventPublisher源码及说明
        • 发布事件
        • 事件示例1
          • 1.自定义事件
        • 2.自定义事件监听器
          • 3.测试
        • 事件示例2:正常业务使用
          • 事件发布对象
          • 测试

Spring5.3学习——from 官网day1-1

前言

本系列为系统的spring框架学习系列,源于官方文档5.3.23版本,本系列文章是我第二次对于官网内容学习,也更加细致,所有内容均为自我总结,并非复制官网内容,若有错误的地方敬请指出,本系列并不太适合新生学习,很多都是源码阅读

概述

  • Spring是当前企业级Java应用最常用的框架
  • 支持Groovy以及Kotlin作为JVM上的代替语言
  • JDK版本建议8+,请大家逐渐适应使用11
  • Spring应用可以以jar包方式长时间的运行
  • Spring是开源的
  • Spring Framework就是我们常说的Spring框架
  • Spring框架是分模块的,应用程序可以自由的选择需要的模块
  • 核心容器模块包括配置模型和依赖注入机制
  • Spring提供基础支持,有消息传递,事务数据,持久化,Web,基于Servlet的Spring MVC,反应式Web框架Spring WebFlux

虽然JDK8和9开始相差巨大,但Spring框架支持你部署于更高的版本

Spring的设计理念

  1. 配置而不是代码,意思是Spring更希望我们以配置的方式控制代码切换业务,而不是直接取修改代码(例如:我们一开始选择使用持久化策略为mysql,但是最后实际业务中使用Oracle,此时按照以前的方式,我们需要去修改代码以完成mysql到Oracle的切换,而Spring则可以以修改配置文件的方式进行修改,无需更改一行代码)
  2. 整合而不是造轮子,意思是Spring不希望自己去重复造轮子,而是去整合本来就十分完善的解决策略,使得自身更加灵活,我们甚至可以将Spring看作是容器,而不是框架!
  3. 兼容而不是变革,Spring具有强大的向后兼容性,每一个版本的退出都经过精心的设计管理,方便维护依赖于Spring的应用程序和库,并且十分注重可用性强大API,使得API可以沿用多个版本
  4. 高标准而不是屎山,Spring的设计以及代码设计结构清晰,使用标准,避免循环依赖,粗制乱造的代码

Spring核心:IOC

什么是IOC

IOC:inversion of control,翻译过来就是控制反转,我们也称为依赖注入(dependency injection)
将IOC == DI可不是我说的是官网说的,但是我们常常看视频和一些文章的时候为什么常把DI和IOC并不说是同一个东西呢?
因为我们通常的认为IOC是一种思想,DI则是IOC的体现(但我并不完全同意这种说法,具体请看下面)
我来看一下下面官网对IOC的描述:

IOC是一个过程,对象仅通过构造函数参数、工厂方法的参数或在对象实例被构造或从工厂方法返回后设置的属性来定义它们的依赖关系(即与它们一起工作的其他对象) . 然后容器在创建 bean 时注入这些依赖项。 这个过程基本上是 bean 本身通过使用类的直接构造或诸如服务定位器模式之类的机制来控制其依赖关系的实例化或位置的逆过程(因此称为控制反转)。

看起来不太好理解,那我们直接看解释

解释

  1. IOC指的是将对象的生命周期的权限委托给Spring,最具体的体现就是创建对象的控制权,而不是我们自己去new对象出来

现在我们这样想,平时我们写程序的时候对象需要我能new出来,好比我们吃饭,吃饭的菜需要我们自己去买,然后烧好
现在有了Spring,相当于Spring是一家餐馆,我们要吃什么,只要直接去餐馆里买就行,餐馆根据我们提供的点单就会帮我们准备好饭菜,这就是IOC
同样我们理解一下DI,依赖注入,请问依赖是什么?从哪里来的依赖?我们一下就想到,不就是程序中我们需要一个对象,但是这个对象需要依赖一个外部的jar包,这不就是我们索要的依赖吗!我们将这个也想像称一个菜单,那么菜单上的菜品就是对象,组成菜品所要的原材料就是依赖,接下来注入就是指将所需要的菜品从原材料做好给我们食用(使用)咯!我们将外部依赖转化为内部依赖,这样一想,DI和IOC就是一个概念嘛!
所以实际上DI和IOC是同一个概念的不同角度上的阐述!准确来说是应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源

  1. IOC其实是Java反射机制的具体体现,根据配置文件在运行时动态的去管理对象

为什么这样说呢?我们首先回忆一下,Java是一门静态语言,这就说明Java在不具备反射机制前无法具备动态特性,是反射让Java获得了动态特性吧!那么Spring如何才能根据配置文件运行时动态的管理对象呢?这样一想很明显结果一目了然,肯定是利用了反射才做到的嘛!

IOC容器的包

org.springframework.beansorg.springframework.context包是基础用于 Spring Framework 的 IoC 容器的基础

什么是Bean

在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。 bean 是由 Spring IoC 容器实例化、组装和管理的对象。 否则,bean 只是应用程序中的众多对象之一。 Bean 以及它们之间的依赖关系反映在容器使用的配置元数据中。

BeanFactory接口简述

BeanFactory接口提供了一种高级配置机制,能够管理任意类型的对象,BeanFactory 提供了配置框架和基本功能

ApplicationContext接口简述

ApplicationContext是BeanFactory的子接口
增加了更多的企业特定功能,添加了以下特性

  1. 更容易与 Spring 的 AOP 功能集成
  2. 消息资源处理(用于国际化)
  3. 活动发布
  4. 应用层特定上下文,例如用于 Web 应用程序的 WebApplicationContext。
    ApplicationContext 是 BeanFactory 的完整超集,专门用于描述 Spring 的 IoC 容器。
    负责实例化bean,配置bean,组装 bean

容器通过读取配置元数据来获取关于要实例化、配置和组装哪些对象的指令。 (配置元数据以 XML、Java 注释或 Java 代码表示。 它允许您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系)

在程序中我们通常使用 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的实例,作为ApplicationContext接口的实现。
如下是Spring容器中应用程序与配置相结合形成完全配置可执行使用的应用程序
在这里插入图片描述

BeanFactory源码

描述

用于访问 Spring bean 容器的根接口。

以下是Bean工厂创建和销毁bean的完整生命周期流程

Bean 工厂实现应尽可能支持标准的 bean 生命周期接口。全套初始化方法及其标准顺序为:

  1. BeanNameAware 的setBeanName
  2. BeanClassLoaderAware 的setBeanClassLoader
  3. BeanFactoryAware 的setBeanFactory
  4. EnvironmentAware 的setEnvironment
  5. EmbeddedValueResolverAware 的setEmbeddedValueResolver
  6. ResourceLoaderAware 的setResourceLoader (仅在应用程序上下文中运行时适用)
  7. ApplicationEventPublisherAware 的setApplicationEventPublisher (仅在应用程序上下文中运行时适用)
  8. MessageSourceAware 的setMessageSource (仅在应用程序上下文中运行时适用)
  9. ApplicationContextAware 的setApplicationContext (仅在应用程序上下文中运行时适用)
  10. ServletContextAware 的setServletContext (仅适用于在 Web 应用程序上下文中运行时)
  11. BeanPostProcessors 的postProcessBeforeInitialization方法
  12. InitializingBean 的afterPropertiesSet
  13. 自定义init-method定义
  14. BeanPostProcessors 的postProcessAfterInitialization方法

在关闭 bean 工厂时,将应用以下生命周期方法:

  1. DestructionAwareBeanPostProcessors 的postProcessBeforeDestruction方法
  2. DisposableBean 的destroy
  3. 自定义destroy-method定义

常量&

用于取消引用FactoryBean实例并将其与 FactoryBean创建的 bean 区分开来。当我们获取某个bean时获取到的是工厂而不是实例

String FACTORY_BEAN_PREFIX = "&";

获取Bean实例

通过Bean的名字获取bean

Object getBean(String name) throws BeansException;

通过Bean名字获取bean并预设返回Bean的类型

行为与getBean(String)相同,但如果 bean 不属于所需类型,则通过抛出 BeanNotOfRequiredTypeException 来提供类型安全度量。

<T> T getBean(String name, Class<T> requiredType) throws BeansException;

通过Bean名字获取bean并通过传入参数进行显示构造

允许指定显式构造函数参数/工厂方法参数,覆盖 bean 定义中指定的默认参数

Object getBean(String name, Object... args) throws BeansException;

通过Bean的类型获取Bean实例

此方法进入ListableBeanFactory按类型查找领域,但也可以转换为基于给定类型名称的常规按名称查找。要跨 bean 集进行更广泛的检索操作,请使用ListableBeanFactory和/或BeanFactoryUtils 。

<T> T getBean(Class<T> requiredType) throws BeansException;

通过Bean名字获取bean并通过类型约束传入参数进行显示构造

<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

获取Bean的提供者

通过传入Bean的类型获取Bean的提供者

<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

通过ResolvableType对Bean类型进行规范

ResolvableType的.forType(Class<T> classType)方法获取到传入Bean的类型进行规范

<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

判断bean工厂中是否含有指定Bean

判断这个 bean 工厂是否包含 bean 定义或外部注册的具有给定名称的单例实例?(如果给定的名称是别名,它将被翻译回相应的规范 bean 名称。)
如果这个工厂是分层的,如果在这个工厂实例中找不到 bean,将询问各个父工厂,直到查询完毕

boolean containsBean(String name);

判断Bean为单例或多例

首先我们要知道什么是Spring中的单例Bean、多例Bean(原型Bean)
单例:每次我们获取bean时并不会重新创建一个新的实例,而是永远使用一个
多例:每次我们获取bean时会创建一个独立的新的实例

判断Bean是否为单例Bean

返回false并不代表这个Bean是个独立实例,仅仅表示它是非单例实例(可能在某些特定作用域里是这样的),我们需要使用isPrototype方法显式检查独立实例

boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

判断Bean是否为多例Bean

判断这个bean是原型吗?也就是说, getBean总是会返回独立的实例吗?(true表示是原型会返回独立的实例)
返回false仅仅表示非独立实例,也可能对应于作用域 bean。使用isSingleton操作显式检查共享单例实例

boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

判断类型是否匹配

判断传入的Bean类型是否和指定类型相符合

boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

获取Bean的类型

根据传入的Bean名称获取Bean的类型

Class<?> getType(String name) throws NoSuchBeanDefinitionException;

根据allowFactoryBeanInit标志,如果没有可用的早期类型信息,这可能会导致对先前未初始化的FactoryBean进行初始化

Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

返回给定 bean 名称的别名

在getBean调用中使用时,所有这些别名都指向同一个 bean。
如果给定名称是别名,则将返回相应的原始 bean 名称和其他别名(如果有),原始 bean 名称是数组中的第一个元素。遍历数组会获取除了你传入的名称以为所有的别名

String[] getAliases(String name);

简单示例

如下给出了所有的方法示例

TestBean

创建该类指明@Component注解,其中@Bean注解的name属性它用于指定别名

@Component
public class TestBean {@Beanpublic void test(){System.out.println("use function name as bean name");}@Bean(name = {"testing","myName","Name2"})public void test2(){System.out.println("use bean name");}
}

测试

@SpringBootApplication
public class Beanfactory1Application {public static void main(String[] args) {final ConfigurableApplicationContext run = SpringApplication.run(Beanfactory1Application.class, args);/**通过默认方法名作为Bean实例名称,获取bean实例* @Bean*     public void test(){*         System.out.println("use function name as bean name");*     }*/run.getBean("test");//通过bean的类型获取Bean实例(类)final TestBean testBean = run.getBean("testBean", TestBean.class);testBean.test2();//通过bean名称获取bean(@Bean("testing"))run.getBean("testing");//获取Bean的提供者final ObjectProvider<? extends TestBean> beanProvider = run.getBeanProvider(testBean.getClass());System.out.println(beanProvider);final ObjectProvider<Object> beanProvider1 = run.getBeanProvider(ResolvableType.forType(testBean.getClass()));System.out.println(beanProvider1);//判断是否含有BeanSystem.out.println(run.containsBean("testing"));//判断是否单例System.out.println(run.isSingleton("testing"));//判断是否多例System.out.println(run.isPrototype("testBean"));//判断传入的Bean类型是否和指定类型相符合System.out.println(run.isTypeMatch("testBean", TestBean.class));final Class<?> testing = run.getType("testing");System.out.println(testing);final Class<?> testBean1 = run.getType("testBean", false);System.out.println(testBean1);//这里并没有有别名所有会引发ArrayIndexOutOfBoundsException数组越界final String[] beanAliasesName = run.getAliases("myName");System.out.println(beanAliasesName[0]);for (String s : beanAliasesName) {System.out.println("-----------------");System.out.println(s);}}}

在这里插入图片描述

ApplicationContext扩展说明

由类图可以看出,ApplicationContext接口扩展了MessageSource, ResourcePatternResolver, ApplicationEventPublisher,EnvironmentCapable四个接口,接下来我们详细看一下源码
在这里插入图片描述

MessageSource源码及说明

用于解析消息的策略接口,支持此类消息的参数化和国际化
我们要知道的是我们必须要由相关的映射文件才可以进行匹配解析,需要以Locale类进行标准映射如下:

public static final Locale ENGLISH = createConstant("en", "");/** Useful constant for language.*/public static final Locale FRENCH = createConstant("fr", "");/** Useful constant for language.*/public static final Locale GERMAN = createConstant("de", "");/** Useful constant for language.*/public static final Locale ITALIAN = createConstant("it", "");/** Useful constant for language.*/public static final Locale JAPANESE = createConstant("ja", "");/** Useful constant for language.*/public static final Locale KOREAN = createConstant("ko", "");/** Useful constant for language.*/public static final Locale CHINESE = createConstant("zh", "");/** Useful constant for language.*/public static final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");/** Useful constant for language.*/public static final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");/** Useful constant for country.*/public static final Locale FRANCE = createConstant("fr", "FR");/** Useful constant for country.*/public static final Locale GERMANY = createConstant("de", "DE");/** Useful constant for country.*/public static final Locale ITALY = createConstant("it", "IT");/** Useful constant for country.*/public static final Locale JAPAN = createConstant("ja", "JP");/** Useful constant for country.*/public static final Locale KOREA = createConstant("ko", "KR");

获取消息并进行国际化

尝试解决该消息。如果未找到消息,则返回默认消息。

String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);

尝试解决该消息。如果找不到消息,则视为错误

String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

尝试使用传入的MessageSourceResolvable参数中包含的所有属性来解析消息。
注意:我们必须在此方法上抛出NoSuchMessageException ,因为在调用此方法时,我们无法确定可解析的defaultMessage属性是否为null

String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

示例

1.编写properties设置映射关系

在这里插入图片描述

messages.properties什么都不写

messages_en.properties
hi=say hi
messages_zh.properties
hi=你好

2.编写国际化信息转换

System.out.println(run.getMessage("hi", null, Locale.CHINA));System.out.println(run.getMessage("hi",null,Locale.ENGLISH));

我们可以看到输出就是和我们映射相同的内容
在这里插入图片描述

ResourceLoader源码及说明

用于加载资源(例如,类路径或文件系统资源)的策略接口
DefaultResourceLoader是一个独立的实现,可以在 ApplicationContext 之外使用,也被ResourceEditor使用。
当在 ApplicationContext 中运行时,可以使用特定上下文的资源加载策略从字符串中填充Resource和Resource[]类型的 Bean 属性。

常量

从类路径加载的伪 URL 前缀:“classpath:”

String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

我们可以看到这个不是直接写的classpath:这样的字符串而是使用ResourceUtils这个抽象类中的常量,所以我们下面看一下ResourceUtils

ResourceUtils源码及说明

用于将资源位置解析为文件系统中的文件的实用方法。主要供框架内部使用,在package org.springframework.util;包下,主要提供与ResourceLoader的getResource()方法将任意位置的Resource对象进行加载

常量
	/** Pseudo URL prefix for loading from the class path: "classpath:". */public static final String CLASSPATH_URL_PREFIX = "classpath:";/** URL prefix for loading from the file system: "file:". */public static final String FILE_URL_PREFIX = "file:";/** URL prefix for loading from a jar file: "jar:". */public static final String JAR_URL_PREFIX = "jar:";/** URL prefix for loading from a war file on Tomcat: "war:". */public static final String WAR_URL_PREFIX = "war:";/** URL protocol for a file in the file system: "file". */public static final String URL_PROTOCOL_FILE = "file";/** URL protocol for an entry from a jar file: "jar". */public static final String URL_PROTOCOL_JAR = "jar";/** URL protocol for an entry from a war file: "war". */public static final String URL_PROTOCOL_WAR = "war";/** URL protocol for an entry from a zip file: "zip". */public static final String URL_PROTOCOL_ZIP = "zip";/** URL protocol for an entry from a WebSphere jar file: "wsjar". */public static final String URL_PROTOCOL_WSJAR = "wsjar";/** URL protocol for an entry from a JBoss jar file: "vfszip". */public static final String URL_PROTOCOL_VFSZIP = "vfszip";/** URL protocol for a JBoss file system resource: "vfsfile". */public static final String URL_PROTOCOL_VFSFILE = "vfsfile";/** URL protocol for a general JBoss VFS resource: "vfs". */public static final String URL_PROTOCOL_VFS = "vfs";/** File extension for a regular jar file: ".jar". */public static final String JAR_FILE_EXTENSION = ".jar";/** Separator between JAR URL and file path within the JAR: "!/". */public static final String JAR_URL_SEPARATOR = "!/";/** Special separator between WAR URL and jar part on Tomcat. */public static final String WAR_URL_SEPARATOR = "*/";
判断给定的资源是否为URL

需要传入一个目标资源路径进行判断

  1. 判断传入路径不为空
  2. 判断传入路径的起始为classpath:
  3. 若起始不为classpath:则尝试new URL并传入目标资源路径作为构造函数的参数,并返回true
public static boolean isUrl(@Nullable String resourceLocation) {
//1. if (resourceLocation == null) {return false;}//2.if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {return true;}try {new URL(resourceLocation);return true;}catch (MalformedURLException ex) {return false;}}//new URL(String resourceLocation)
//从String表示创建一个URL对象
public URL(String spec) throws MalformedURLException {this(null, spec);}
public URL(URL context, String spec) throws MalformedURLException {this(context, spec, null);}public URL(URL context, String spec, URLStreamHandler handler)throws MalformedURLException{String original = spec;int i, limit, c;int start = 0;String newProtocol = null;boolean aRef=false;boolean isRelative = false;// Check for permission to specify a handlerif (handler != null) {SecurityManager sm = System.getSecurityManager();if (sm != null) {checkSpecifyHandler(sm);}}try {limit = spec.length();while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {limit--;        //eliminate trailing whitespace}while ((start < limit) && (spec.charAt(start) <= ' ')) {start++;        // eliminate leading whitespace}if (spec.regionMatches(true, start, "url:", 0, 4)) {start += 4;}if (start < spec.length() && spec.charAt(start) == '#') {/* we're assuming this is a ref relative to the context URL.* This means protocols cannot start w/ '#', but we must parse* ref URL's like: "hello:there" w/ a ':' in them.*/aRef=true;}for (i = start ; !aRef && (i < limit) &&((c = spec.charAt(i)) != '/') ; i++) {if (c == ':') {String s = toLowerCase(spec.substring(start, i));if (isValidProtocol(s)) {newProtocol = s;start = i + 1;}break;}}// Only use our context if the protocols match.protocol = newProtocol;if ((context != null) && ((newProtocol == null) ||newProtocol.equalsIgnoreCase(context.protocol))) {// inherit the protocol handler from the context// if not specified to the constructorif (handler == null) {handler = context.handler;}// If the context is a hierarchical URL scheme and the spec// contains a matching scheme then maintain backwards// compatibility and treat it as if the spec didn't contain// the scheme; see 5.2.3 of RFC2396if (context.path != null && context.path.startsWith("/"))newProtocol = null;if (newProtocol == null) {protocol = context.protocol;authority = context.authority;userInfo = context.userInfo;host = context.host;port = context.port;file = context.file;path = context.path;isRelative = true;}}if (protocol == null) {throw new MalformedURLException("no protocol: "+original);}// Get the protocol handler if not specified or the protocol// of the context could not be usedif (handler == null &&(handler = getURLStreamHandler(protocol)) == null) {throw new MalformedURLException("unknown protocol: "+protocol);}this.handler = handler;i = spec.indexOf('#', start);if (i >= 0) {ref = spec.substring(i + 1, limit);limit = i;}/** Handle special case inheritance of query and fragment* implied by RFC2396 section 5.2.2.*/if (isRelative && start == limit) {query = context.query;if (ref == null) {ref = context.ref;}}handler.parseURL(this, spec, start, limit);} catch(MalformedURLException e) {throw e;} catch(Exception e) {MalformedURLException exception = new MalformedURLException(e.getMessage());exception.initCause(e);throw exception;}}

说明:

  • 进入new URL后其中public URL(URL context, String spec, URLStreamHandler handler)中仅spec有传值,其他两个参数为空
  • 进入到try子块中,首先limit获取为spec的字符串长度,接下来通过 while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { limit--; //eliminate trailing whitespace }这个循环消除路径中尾部的空格,这说明如果我们不小心打了空格也没有关系
  • 然后是去除首部的空格,这里可以借鉴一下
  • 使用regionMatches方法将spec变量和url:两个字符串相比较看看是不是相同,若是则跳过4个字符长度start += 4(忽略大小写,使用start作为偏移量【这里的目的就是不受到空格的影响,只比较非空格部分】,于url:进行比较,比较4个字符长度)
  • 判断start当前是否小于spec的字符串长度,并且其起始位置为#,若是则aRef为true
  • 进行for循环目的是判断传入的资源地址是否为协议格式
    • 当匹配是协议时URL类的属性protocol附上我们传入的目标地址
  • 最后对URL进行解析
获取文件

将给定的资源 URL 解析为java.io.File ,即文件系统中的文件

//1.
public static File getFile(URL resourceUrl)
//2.第二个参数表示描述信息
public static File getFile(URL resourceUrl, String description)
//3.
public static File getFile(URI resourceUri)
//4.
public static File getFile(URI resourceUri, String description)
判断给定的路径是否为文件路径
public static boolean isFileURL(URL url)
判断是否为jar包路径

确定给定的 URL 是否指向 jar 文件中的资源。即具有协议“jar”、“war”、“zip”、“vfszip”或“wsjar”。

public static boolean isJarURL(URL url) 
判断是否指定jar包本身的路径
public static boolean isJarFileURL(URL url) 
从给定的 URL 中提取实际 jar 文件的 URL
public static URL extractJarFileURL(URL jarUrl) 
为给定的位置字符串创建一个 URI 实例,首先用“%20”URI 编码替换空格
public static URI toURI(String location)public static URI toURI(URL url)
设定使用缓存标志

对于基于 JNLP 的资源,首选false ,但将标志保留为true

public static void useCachesIfNecessary

返回指定资源位置的Resource句柄

句柄应始终是可重用的资源描述符,允许多个Resource.getInputStream()调用。

必须支持完全限定的 URL,例如“file:C:/test.dat”。
必须支持类路径伪 URL,例如“classpath:test.dat”。
应该支持相对文件路径,例如“WEB-INF/test.dat”。 (这将是特定于实现的,通常由 ApplicationContext 实现提供。)

请注意, Resource句柄并不意味着现有资源;您需要调用Resource.exists来检查是否存在

Resource getResource(String location);

获取类加载器

获取的是ResourceLoader使用的ClassLoader

ClassLoader getClassLoader();

ResourcePatternResolver源码及说明

这是ResourceLoader接口的扩展。可以检查传入的ResourceLoader

常量

表示resource路径下所有的资源路径

String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

根据传入目标资源地址获取资源

将给定的位置模式解析为Resource对象

Resource[] getResources(String locationPattern) throws IOException;

示例:获取资源

final ConfigurableApplicationContext run = SpringApplication.run(Beanfactory1Application.class, args);
//当前项目下的资源final Resource[] resources = run.getResources("classpath:application.properties");for (Resource resource : resources) {System.out.println(resource);}
//所有包括项目外部库中的资源final Resource[] resources1 = run.getResources("classpath*:META-INF/spring.factories");for (Resource resource : resources1) {System.out.println(resource);}

在这里插入图片描述

EnvironmentCapable源码及说明

指示包含和公开Environment引用的组件的接口,意思是整个Spring的环境

所有 Spring 应用程序上下文都是 EnvironmentCapable,并且该接口主要用于在框架方法中执行instanceof检查,这些方法接受 BeanFactory 实例,这些实例可能实际上是也可能不是 ApplicationContext 实例,以便与环境交互(如果确实可用)。
如前所述, ApplicationContext扩展了 EnvironmentCapable,因此公开了一个getEnvironment()方法;但是, ConfigurableApplicationContext重新定义getEnvironment()并缩小了签名以返回ConfigurableEnvironment 。效果是 Environment 对象在从 ConfigurableApplicationContext 访问之前是“只读的”,此时它也可以被配置。

获取当前环境

返回与此组件关联的Environment

Environment getEnvironment();

示例:获取当前环境参数

final ConfigurableApplicationContext run = SpringApplication.run(Beanfactory1Application.class, args);System.out.println(run.getEnvironment().getProperty("java_home"));System.out.println(run.getEnvironment().getProperty("server.port"));System.out.println(run.getEnvironment().getProperty("define.testName"));

在这里插入图片描述

以下是application.properties中的内容

server.port=8557define.testName=hello spring

当然我们可以直接获取系统所有参数

System.out.println(run.getEnvironment().getSystemEnvironment());
{USERDOMAIN_ROAMINGPROFILE=SYFS-COMPUTER, PROCESSOR_LEVEL=6, Maven_HOME=D:\maven\apache-...}

ApplicationEventPublisher源码及说明

封装事件发布功能的接口。
作为ApplicationContext的超级接口

发布事件

通知在此应用程序中注册的所有匹配的侦听器一个事件。
如果指定的event不是ApplicationEvent ,则将其包装在PayloadApplicationEvent中

//这是默认实现
default void publishEvent(ApplicationEvent event) {publishEvent((Object) event);}void publishEvent(Object event);

大家请关注这句话如果指定的event不是ApplicationEvent,则将其包装在PayloadApplicationEvent中,这句话说明了如果我们要自己定义一个事件,则需要继承ApplicationEvent

事件示例1

1.自定义事件
public class EasyEvent extends ApplicationEvent {public EasyEvent(Object source) {super(source);}
}

2.自定义事件监听器

我们要确保使用了@Component注册为组件,如下

@Component
public class DefineEventListener {@EventListenerpublic void defineListener(EasyEvent event){System.out.println("========Listen======");System.out.println(event);}
}
3.测试
final ConfigurableApplicationContext run = SpringApplication.run(Beanfactory1Application.class, args);
//发布事件
run.publishEvent(new EasyEvent(run));

在这里插入图片描述

事件示例2:正常业务使用

以下场景:我们需要对某个事件进行相关处理,当我们接收到用户请求之后,我们需要发送一个短信给用户,我们就可以使用事件

事件发布对象
@Component
public class DefineEventPublisher {@Autowiredprivate ApplicationEventPublisher publisher;public void registerEvent(){publisher.publishEvent(new EasyEvent(this));}}
测试
final ConfigurableApplicationContext run = SpringApplication.run(Beanfactory1Application.class, args);run.getBean(DefineEventPublisher.class).registerEvent();

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_10436.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matlab论文插图绘制模板第48期—平行坐标图(Parallelplot)

​上一期文章中&#xff0c;分享了Matlab帕累托图的绘制模板&#xff1a; 这一次&#xff0c;再来分享一种特殊的线图&#xff1a;平行坐标图。 ‘平行坐标图是一种通常的可视化方法&#xff0c;用于对高维几何和多元数据的可视化……为了克服传统的笛卡尔直角坐标系容易耗尽空…

好心情精神心理科:80%双相情感障碍被误诊,千万注意鉴别

双相情感障碍又称躁郁症&#xff0c;其表现复杂&#xff0c;容易与其他精神疾病&#xff08;包括边缘型人格障碍&#xff09;相混淆&#xff0c;超过80%的患者未能得到正确诊断。 具体如何区分双相情感障碍与边缘型人格障碍&#xff1f;在回答这个问题之前&#xff0c;好心情精…

从规模走向规模经济,锅圈食汇回归餐饮初心

预制菜源自美国&#xff0c;在日本因冷链技术发展而普及。后疫情时代&#xff0c;预制菜在中国餐饮市场加速渗透&#xff0c;成为行业的新风向。 9月&#xff0c;第一财经与CBNData发布“Growth502022中国新消费品牌年度增长力榜单”&#xff0c;预制菜品牌锅圈食汇入选。 锅…

设计模式学习笔记--责任链模式

责任链模式 责任链模式是一种对象的行为模式。在责任链模式里&#xff0c;很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递&#xff0c;直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求&…

Tuxera NTFS21Mac苹果电脑读取硬盘磁盘软件

我们经常会使用移动硬盘或 U 盘进行大体积文件的分享、携带。但有时候别人提供的NTFS移动硬盘或者U 盘在 Mac 电脑中只能读取&#xff0c;无法将文件导入到其中。这是因为常见的 NTFS 硬盘格式在 Mac 中不能兼容。 当你从 Windows 转到了 Mac 平台&#xff0c;可能会发现之前用…

RocketMQ-流程图-概念

文章目录RocketMq的角色消息发送的流程RocketMq的角色 Producer&#xff1a;消息的发送者&#xff0c;生产者&#xff1b;举例&#xff1a;发件人Consumer&#xff1a;消息接收者&#xff0c;消费者&#xff1b;举例&#xff1a;收件人Broker&#xff1a;暂存和传输消息的通道…

Python数据分析教程(一):Numpy

数据的纬度 一维数据:列表和集合类型二维数据:列表类型多维数据:列表类型高维数据:字典类型或数据表示格式,如json、xml、yaml维度:一组数据的组织形式列表和数组:一组数据的有序结构Numpy Numpy介绍NumPy是一个开源的Python科学计算基础库,包含:一个强大的N维数组对象…

渗透测试神器Nmap使用教程

渗透测试神器Nmap使用教程1.nmap简介2.常用参数3.nmap实战命令1.nmap简介 Nmap &#xff08;网络映射器&#xff09;是Gordon Lyon最初编写的一种安全扫描器&#xff0c;用于发现计算机网络上的主机和服务&#xff0c;从而创建网络的“映射”。为了实现其目标&#xff0c;Nmap…

java计算机毕业设计基于安卓Android的金融保险app(源码+系统+mysql数据库+Lw文档)

项目介绍 计算机信息技术的发展&#xff0c;推动了金融保险信息化管理的进程&#xff0c;并随着互联网概念的提出&#xff0c;各种互联网软件也应运而生。在传统的管理中&#xff0c;各种信息管理难&#xff0c;传播速度慢&#xff0c;需要耗费很长时间统计核查&#xff0c;不…

Oracel中视图相关概念和操作(一)

目录 1.视图概念&#xff08;有必要&#xff09; &#xff08;1&#xff09;视图基本概念 &#xff08;2&#xff09;视图和定义的表的联系 &#xff08;3&#xff09;视图的优点 2.创建视图 &#xff08;1&#xff09;使用SQL DEVELOPER创建视图&#xff08;可视化&#x…

如何正确的审核交易商牌照?这些雷区你不得不防

对于外汇平台来说&#xff0c;交易牌照可以说是重中之重&#xff0c;一个交易没有牌照&#xff0c;可以说是没有任何约束&#xff0c;属于监管裸奔状态&#xff0c;这种平台10个有10个就是黑平台。但也正因如此&#xff0c;无数黑平台也会在牌照上面做手脚&#xff0c;这些人手…

基于stm32单片机甲醛烟雾温湿度检测仪设计

目录 第1章 绪论 1.1 引言 1.1.1甲醛的特性及危害 1.1.2甲醛的来源 1.2甲醛检测仪的种类 第&#xff12;章 概述 2.1系统总概述 2.2总体方案设计 2.3硬件设计 2.4软件设计 第3章 硬件设计 3.1 硬件设计主电路图 3.2 硬件选择 3.2.1 MCU的选择与简介 3.2.3 …

Gimbal Lock欧拉角死锁问题

技术背景 在前面几篇跟SETTLE约束算法相关的文章(1, 2, 3)中&#xff0c;都涉及到了大量的向量旋转的问题--通过一个旋转矩阵&#xff0c;给定三个空间上的欧拉角\(\alpha, \beta, \gamma\)&#xff0c;将指定的向量绕对应轴进行旋转操作。而本文主要就阐述这些旋转操作中&…

复习十二:广义表

一、广义表的定义及其重要特性 广义表简称表&#xff0c;它是线性表的推广。一个广义表是n(n>0)个元素的一个序列&#xff0c;若n0时&#xff0c;则称为空表&#xff1b; 广义表中有两种数据元素&#xff0c;即有两种结构的结点&#xff1a;表结点和原子结点&#xff1b;广义…

大数据ClickHouse进阶(十一):ClickHouse的Join子句

文章目录 ClickHouse的Join子句 一、连接精度

Springcloud的学习笔记(二)

Springcloud学习笔记(一) 目录8 消费者订单模块9 重构10 Eureka服务注册与发现10.1 Eureka基础知识10.2 EurekaServer服务端安装10.3 支付微服务8001入驻进EurekaServer10.4 订单微服务81入驻进EurekaServer10.5 Eureka集群原理说明10.6 Eureka集群环境构建10.7 订单支付两微服…

ASR6500S SIP模块与SX1262系列集成替代SX1278 SX1262内核+RF前端

ASR6500S是一系列LoRa SIP模块,集成了RF前端和LoRa无线电收发器SX1262系列,支持LoRa 和FSK调制。LoRa技术是一种针对LPWAN应用的低数据速率、超远程、超低功耗通信进行优化的 广谱协议。 ASR6500S设计为电池寿命长,有功接收电流消耗4.2 mA,最大发射功率可达+22dBm。该模块实…

Shell之练习题

目录 一、练习一 1.1、分析 1.2、编辑脚本文件 1.3、测试 二、练习二 2.1、分析 2.2、编辑脚本文件 ​2.3、测试 三、练习三 3.1、分析 3.2、编辑脚本文件 ​3.3、测试 四、练习四 4.1、分析 4.2、编辑脚本文件 4.3、测试​ 一、练习一 需求&#xff1a;给定一…

Python量化交易实战:获取股票数据并做分析处理

量化交易&#xff08;也称自动化交易&#xff09;是一种应用数学模型帮助投资者进行判断&#xff0c;并且根据计算机程序发送的指令进行交易的投资方式&#xff0c;它极大地减少了投资者情绪波动的影响。量化交易的主要优势如下&#xff1a; 快速检测客观、理性自动化 量化交易…

Prompt Learning : Prefix Tuning

Prompt Learning 首先Prompt Learning 称为提示学习&#xff0c;是最近比较火的一种NLP范式&#xff0c;过去“PretrainFinetuning"的模式虽然能够利用预训练语言模型在大规模语料库上的预训练带来的初始优良性能&#xff0c;但是对于不同的NLP任务&#xff0c;比如NER&a…