一、Spring体系结构:

Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring 是模块化的,允许你挑选和选择适用于你的模块,不必要把剩余部分也引入。下面的部分对在 Spring 框架中所有可用的模块给出了详细的介绍。

Spring 框架提供约 20 个模块,可以根据应用程序的要求来使用。

Spring 体系结构

核心容器

核心容器由spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

  • spring-core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
  • spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。
  • context模块建立在由corebeans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。Context模块继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过Servelet容器)等功能。Context模块也支持Java EE的功能,比如EJB、JMX和远程调用等。ApplicationContext接口是Context模块的焦点。spring-context-support提供了对第三方库集成到Spring上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。
  • spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等。

它们的完整依赖关系如下图所示:

Spring 体系结构

数据访问/集成

数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

(注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)

  • JDBC 模块提供了JDBC抽象层,它消除了冗长的JDBC编码和对数据库供应商特定错误代码的解析。
  • ORM 模块提供了对流行的对象关系映射API的集成,包括JPA、JDO和Hibernate等。通过此模块可以让这些ORM框架和spring的其它功能整合,比如前面提及的事务管理。
  • OXM 模块提供了对OXM实现的支持,比如JAXB、Castor、XML Beans、JiBX、XStream等。
  • JMS 模块包含生产(produce)和消费(consume)消息的功能。从Spring 4.1开始,集成了spring-messaging模块。。
  • 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。(注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细)

Web

Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

  • Web 模块提供面向web的基本功能和面向web的应用上下文,比如多部分(multipart)文件上传功能、使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分。。
  • Web-MVC 模块为web应用提供了模型视图控制(MVC)和REST Web服务的实现。Spring的MVC框架可以使领域模型代码和web表单完全地分离,且可以与Spring框架的其它所有功能进行集成。
  • Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。
  • Web-Portlet 模块提供了用于Portlet环境的MVC实现,并反映了spring-webmvc模块的功能。

其他

还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

  • AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。
  • Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
  • Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。
  • Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。
  • 测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。

二、Spring IOC容器:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z39luR8J-1595843071519)(E:\熙邻\技术分享\2019.08-spring\img\微信图片_20190626204151.png)]

IoC 容器

Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器,Spring容器是生成Bean实例的工厂,并且管理容器中的Bean。

Bean是Spring管理的基本单位,在基于Spring的Java EE应用中,所有的组件都被当成Bean处理,包括数据源、Hibernate的SessionFactory、事务管理器等。在Spring中,Bean的是一个非常广义的概念,任何的Java对象、Java组件都被当成Bean处理。

而且应用中的所有组件,都处于Spring的管理下,都被Spring以Bean的方式管理,Spring负责创建Bean实例,并管理他们的生命周期。Bean在Spring容器中运行,无须感受Spring容器的存在,一样可以接受Spring的依赖注入,包括Bean属性的注入,协作者的注入、依赖关系的注入等。

Spring容器负责创建Bean实例,所以需要知道每个Bean的实现类,Java程序面向接口编程,无须关心Bean实例的实现类;但是Spring容器必须能够精确知道每个Bean实例的实现类,因此Spring配置文件必须精确配置Bean实例的实现类。

BeanFactory 容器

这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。BeanFactory 和相关的接口,比如BeanFactoryAware、DisposableBean、InitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。

在 Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用。

在资源宝贵的移动设备或者基于 applet 的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext,除非你有更好的理由选择 BeanFactory。

ApplicationContext 容器

Application Context 是 BeanFactory 的子接口,也被成为 Spring 上下文。

Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface 接口中定义。

ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀。当然,BeanFactory 仍可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。

最常被使用的 ApplicationContext 接口实现:

  • FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
  • ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
  • WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。

三:Spring Bean定义:BeanDefinition

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。

bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

  • 如何创建一个 bean
  • bean 的生命周期的详细信息
  • bean 的依赖关系

上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。

属性 描述
class 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
name 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope 这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。
constructor-arg 它是用来注入依赖关系的
properties 它是用来注入依赖关系的
autowiring mode 它是用来注入依赖关系的
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法 在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。
destruction 方法 当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

Bean 与 Spring 容器的关系

下图表达了Bean 与 Spring 容器之间的关系:

Spring Bean 定义

四、Spring Bean作用域:

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton

Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示:

作用域 描述
singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值
prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

singleton 作用域:

singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。

当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例。

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton。

prototype 作用域

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

    <!-- 作用域:singleton + prototype --><bean id="user" class="model.User" scope="singleton"><property name="name" value="tony"/><property name="phone" value="13244556677"/></bean>
public static void main(String[] args) {ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");User user = (User)ac.getBean("user");User user2 = (User)ac.getBean("user");System.out.println("user == user2 :" + (user == user2));}

结果:第一种情况:scope="singleton"时,打印结果:user == user2 :true第二种情况:scope="prototype"时,打印结果:user == user2 :false 

五、(重点)Spring Bean生命周期------四个阶段:

Spring Bean的生命周期只有这四个阶段。把这四个阶段和每个阶段对应的扩展点糅合在一起虽然没有问题,但是这样非常凌乱,难以记忆。要彻底搞清楚Spring的生命周期,首先要把这四个阶段牢牢记住。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction

实例化 -> 属性赋值 -> 初始化 -> 销毁

主要逻辑都在doCreate()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。

  • createBeanInstance() -> 实例化
  • populateBean() -> 属性赋值
  • initializeBean() -> 初始化
<bean id="people" class="model.People" init-method="init" destroy-method="destroy"><property name="name" value="tony2"/><property name="gender" value="man"/>
</bean>
public class People {private String name;private String gender;public People() {System.out.println("【构造器--People】调用People无参构造器实例化");}public void init() {System.out.println("【初始化--People】调用People的init()初始化");}public void destroy() {System.out.println("【销毁--People】调用People的destroy()销毁");}public void setName(String name) {System.out.println("【注入属性--People】注入属性name");this.name = name;}public void setGender(String gender) {System.out.println("【注入属性--People】注入属性gender");this.gender = gender;}
}
public static void main(String[] args) {/*** Spring Bean 生命周期共四个阶段:实例化 + 属性设置 + 初始化 + 销毁*/ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext();ac.setConfigLocation("classpath:spring.xml");ac.refresh();ac.destroy();}
打印结果:【构造器--People】调用People无参构造器实例化【注入属性--People】注入属性name【注入属性--People】注入属性gender【初始化--People】调用People的init()初始化【销毁--People】调用People的destroy()销毁
关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种:

第一种是:通过 在xml中定义init-method 和  destory-method方法

第二种是: 通过bean实现InitializingBean和 DisposableBean接口

第三种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作

<bean class="processor.MyBeanPostProcessor" init-method="init" destroy-method="destroy"/>
public class People implements InitializingBean, DisposableBean {....// 初始化时候调用public void afterPropertiesSet() {System.out.println("【InitializingBean接口调用】InitializingBean.afterPropertiesSet()");}// bean销毁前调用public void destroy() {System.out.println("【销毁--People】调用People的destroy()销毁");}
}
public class People implements InitializingBean, DisposableBean {....@PostConstructpublic void  testPostConstruct() {System.out.println("@PostConstruct调用");}@PreDestroypublic void  testPreDestroy() {System.out.println("@PreDestroy调用");}}

三种方式打印顺序:【构造器--People】调用People无参构造器实例化
【注入属性--People】注入属性name
【注入属性--People】注入属性gender
@PostConstruct调用
【InitializingBean接口调用】InitializingBean.afterPropertiesSet()
【初始化--People】调用People的init()初始化
@PreDestroy调用
【DisposableBean接口调用】DisposableBean.destroy()
【销毁--People】调用People的destroy()销毁

六、Spring Bean后置处理器:

容器级别,对所有定义在Spring容器中的bean起作用。

(1)BeanPostProcesser:在Bean初始化前后调用,即 Initialization

postProcessBeforeInitialization:初始化前调用

postProcessAfterInitialization: 初始化后调用

<bean id="people" class="model.People" init-method="init" destroy-method="destroyBean"><property name="name" value="tony2"/><property name="gender" value="man"/>
</bean>
<bean class="processor.MyBeanPostProcessor" init-method="init" destroy-method="destroy"/>
public class MyBeanPostProcessor implements BeanPostProcessor {public MyBeanPostProcessor() {System.out.println("【构造器--BeanPostProcessor】调用BeanPostProcessor无参构造器实例化)");}public void init() {System.out.println("【初始化--BeanPostProcessor】调用BeanPostProcessor的init()初始化");}public void destroy() {System.out.println("【销毁--BeanPostProcessor】调用BeanPostProcessor的destroy()销毁");}public Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessBeforeInitialization()");return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) {System.out.println("【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessAfterInitialization()");return bean;}
}

【构造器--BeanPostProcessor】调用BeanPostProcessor无参构造器实例化
【初始化--BeanPostProcessor】调用BeanPostProcessor的init()初始化
【构造器--People】调用People无参构造器实例化
【注入属性--People】注入属性name
【注入属性--People】注入属性gender
【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessBeforeInitialization()
【初始化--People】调用People的init()初始化
【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessAfterInitialization()
【销毁--People】调用People的destroy()销毁
【销毁--BeanPostProcessor】调用BeanPostProcessor的destroy()销毁

(2)InstantiationAwareBeanPostProcessorAdapter:在Bean实例化前后调用,即Instantiation

postProcessBeforeInstantiation: 实例化前调用

postProcessAfterInstantiation:实例化后调用

<bean id="people" class="model.People" init-method="init" destroy-method="destroyBean"><property name="name" value="tony2"/><property name="gender" value="man"/>
</bean>
<bean class="processor.MyInstantiationAwareBeanPostProcessorAdapter" init-method="init" destroy-method="destroy"/>
public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {public MyInstantiationAwareBeanPostProcessorAdapter() {System.out.println("【构造器--InstantiationAwareBeanPostProcessorAdapter】调用InstantiationAwareBeanPostProcessorAdapter无参构造器实例化)");}public void init() {System.out.println("【初始化--InstantiationAwareBeanPostProcessorAdapter】调用InstantiationAwareBeanPostProcessorAdapter的init()初始化");}public void destroy() {System.out.println("【销毁--InstantiationAwareBeanPostProcessorAdapter】调用InstantiationAwareBeanPostProcessorAdapter的destroy()销毁");}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {System.out.println("【InstantiationAwareBeanPostProcessorAdapter调用】 方法:postProcessBeforeInstantiation()");return super.postProcessBeforeInstantiation(beanClass, beanName);}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println("【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessAfterInstantiation()");return super.postProcessAfterInstantiation(bean, beanName);}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println("【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessProperties()");return super.postProcessProperties(pvs, bean, beanName);}
}

【构造器--InstantiationAwareBeanPostProcessorAdapter】调用无参构造器实例化)
【初始化--InstantiationAwareBeanPostProcessorAdapter】调用init()初始化
【InstantiationAwareBeanPostProcessorAdapter调用】 方法:postProcessBeforeInstantiation()
【构造器--People】调用People无参构造器实例化
【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessAfterInstantiation()
【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessProperties()
【注入属性--People】注入属性name
【注入属性--People】注入属性gender
【初始化--People】调用People的init()初始化
【销毁--People】调用People的destroy()销毁
【销毁--InstantiationAwareBeanPostProcessorAdapter】调用destroy()销毁

(3)BeanFactoryPostProcessor: 在所有Bean实例化前调用

<bean id="people" class="model.People" init-method="init" destroy-method="destroyBean"><property name="name" value="tony2"/><property name="gender" value="man"/>
</bean>
<bean class="processor.MyBeanFactoryPostProcessor" init-method="init" destroy-method="destroy"/>
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {public MyBeanFactoryPostProcessor() {System.out.println("【构造器--BeanFactoryPostProcessor】调用无参构造器实例化");}public void init() {System.out.println("【初始化--BeanFactoryPostProcessor】调用init()初始化");}public void destroy() {System.out.println("【销毁--BeanFactoryPostProcessor】调用destroy()销毁");}public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {System.out.println("【方法调用--BeanFactoryPostProcessor】调用postProcessBeanFactory()");}
}

【构造器--BeanFactoryPostProcessor】调用无参构造器实例化
【初始化--BeanFactoryPostProcessor】调用init()初始化
【方法调用--BeanFactoryPostProcessor】调用postProcessBeanFactory()
【构造器--People】调用People无参构造器实例化
【注入属性--People】注入属性name
【注入属性--People】注入属性gender
【初始化--People】调用People的init()初始化
【销毁--People】调用People的destroy()销毁
【销毁--BeanFactoryPostProcessor】调用destroy()销毁

(4)Spring Bean 后置处理器调用顺序打印:

【构造器--BeanFactoryPostProcessor】调用无参构造器实例化
【初始化--BeanFactoryPostProcessor】调用init()初始化
【方法调用--BeanFactoryPostProcessor】调用postProcessBeanFactory()
【构造器--BeanPostProcessor】调用BeanPostProcessor无参构造器实例化)
【初始化--BeanPostProcessor】调用BeanPostProcessor的init()初始化
【构造器--InstantiationAwareBeanPostProcessorAdapter】调用无参构造器实例化)
【初始化--InstantiationAwareBeanPostProcessorAdapter】调用init()初始化
【InstantiationAwareBeanPostProcessorAdapter调用】 方法:postProcessBeforeInstantiation()
【构造器--People】调用People无参构造器实例化
【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessAfterInstantiation()
【InstantiationAwareBeanPostProcessorAdapter调用】方法:postProcessProperties()
【注入属性--People】注入属性name
【注入属性--People】注入属性gender
【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessBeforeInitialization()
@PostConstruct调用
【InitializingBean接口调用】InitializingBean.afterPropertiesSet()
【初始化--People】调用People的init()初始化
【方法调用--BeanPostProcessor】调用BeanPostProcessor的postProcessAfterInitialization()
@PreDestroy调用
【DisposableBean接口调用】DisposableBean.destroy()
【销毁--People】调用People的destroy()销毁
【销毁--InstantiationAwareBeanPostProcessorAdapter】调用destroy()销毁
【销毁--BeanPostProcessor】调用BeanPostProcessor的destroy()销毁
【销毁--BeanFactoryPostProcessor】调用destroy()销毁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n8VJAZbE-1595843071523)(E:\熙邻\技术分享\2019.08-spring\img\springBean生命周期图.png)]

(5) 后置处理器在Spring底层应用:

七、源码分析:

IOC容器启动过程
资源定位(classpath,filesystem等)
载入,将bean定义转换为内部数据结构BeanDefintion
向IOC容器注册bean
资源定位
定位配置文件,通过BeadDefinetionReader读入配置

refresh方法实现
IOC容器启动方法是ConfigurableApplicationContext中定义的refresh方法,在AbstractApplicationContext中实现

//准备阶段做的是:标记容器为active状态,以及检查当前的运行环境,比如使用log4j,还是jdklog等
prepareRefresh();

//创建beanfactory, 定位资源,载入,装配beandefinetion
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

//初始化beanfactory, 设置contex的classloader

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
//在基本的初始化之后,对beanfactory做一些修改
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

//调用beanfactory后处理器
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);//注册bean后处理器
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);//初始化消息资源,国际化
// Initialize message source for this context.
initMessageSource();// Initialize event multicaster for this context.
initApplicationEventMulticaster();
//在实例化bean之前,做一些工作
// Initialize other special beans in specific context subclasses.
onRefresh();//注册 ApplicationListener监听器
// Check for listener beans and register them.
registerListeners();//实例化bean
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);//发布bean正常响应事件,初始化bean生命周期处理器
// Last step: publish corresponding event.
finishRefresh();

Spring容器的refresh()【创建刷新】;
1、prepareRefresh()刷新前的预处理;

1)、initPropertySources()初始化一些属性设置;子类自定义个性化的属性设置方法;
2)、getEnvironment().validateRequiredProperties();检验属性的合法等
3)、earlyApplicationEvents= new LinkedHashSet<ApplicationEvent>();保存容器中的一些早期的事件;

2、obtainFreshBeanFactory();获取BeanFactory;
1)、refreshBeanFactory();刷新【创建】BeanFactory;
创建了一个this.beanFactory = new DefaultListableBeanFactory();
设置id;
2)、getBeanFactory();返回刚才GenericApplicationContext创建的BeanFactory对象;
3)、将创建的BeanFactory【DefaultListableBeanFactory】返回;
3、prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置);
1)、设置BeanFactory的类加载器、支持表达式解析器…
2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
3)、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
4)、注册可以解析的自动装配;我们能直接在任何组件中自动注入:
BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
5)、添加BeanPostProcessor【ApplicationListenerDetector】
6)、添加编译时的AspectJ;
7)、给BeanFactory中注册一些能用的组件;
environment【ConfigurableEnvironment】、
systemProperties【Map<String, Object>】、
systemEnvironment【Map<String, Object>】
4、postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作;
1)、子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
以上是BeanFactory的创建及预准备工作============
5、invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessor的方法;
BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化之后执行的;
两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
先执行BeanDefinitionRegistryPostProcessor
1)、获取所有的BeanDefinitionRegistryPostProcessor;
2)、看先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor、
postProcessor.postProcessBeanDefinitionRegistry(registry)
3)、在执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor;
postProcessor.postProcessBeanDefinitionRegistry(registry)
4)、最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors;
postProcessor.postProcessBeanDefinitionRegistry(registry)

	再执行BeanFactoryPostProcessor的方法1)、获取所有的BeanFactoryPostProcessor2)、看先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor、postProcessor.postProcessBeanFactory()3)、在执行实现了Ordered顺序接口的BeanFactoryPostProcessor;postProcessor.postProcessBeanFactory()4)、最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor;postProcessor.postProcessBeanFactory()

6、registerBeanPostProcessors(beanFactory);注册BeanPostProcessor(Bean的后置处理器)【 intercept bean creation】
不同接口类型的BeanPostProcessor;在Bean创建前后的执行时机是不一样的
BeanPostProcessor、
DestructionAwareBeanPostProcessor、
InstantiationAwareBeanPostProcessor、
SmartInstantiationAwareBeanPostProcessor、
MergedBeanDefinitionPostProcessor【internalPostProcessors】、

	1)、获取所有的 BeanPostProcessor;后置处理器都默认可以通过PriorityOrdered、Ordered接口来执行优先级2)、先注册PriorityOrdered优先级接口的BeanPostProcessor;把每一个BeanPostProcessor;添加到BeanFactory中beanFactory.addBeanPostProcessor(postProcessor);3)、再注册Ordered接口的4)、最后注册没有实现任何优先级接口的5)、最终注册MergedBeanDefinitionPostProcessor;6)、注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否是ApplicationListener,如果是applicationContext.addApplicationListener((ApplicationListener<?>) bean);

7、initMessageSource();初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
1)、获取BeanFactory
2)、看容器中是否有id为messageSource的,类型是MessageSource的组件
如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource;
MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取;
3)、把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale);
8、initApplicationEventMulticaster();初始化事件派发器;
1)、获取BeanFactory
2)、从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster;
3)、如果上一步没有配置;创建一个SimpleApplicationEventMulticaster
4)、将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入
9、onRefresh();留给子容器(子类)
1、子类重写这个方法,在容器刷新的时候可以自定义逻辑;
10、registerListeners();给容器中将所有项目里面的ApplicationListener注册进来;
1、从容器中拿到所有的ApplicationListener
2、将每个监听器添加到事件派发器中;
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
3、派发之前步骤产生的事件;
11、finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例bean;
1、beanFactory.preInstantiateSingletons();初始化后剩下的单实例bean
1)、获取容器中的所有Bean,依次进行初始化和创建对象
2)、获取Bean的定义信息;RootBeanDefinition
3)、Bean不是抽象的,是单实例的,是懒加载;
1)、判断是否是FactoryBean;是否是实现FactoryBean接口的Bean;
2)、不是工厂Bean。利用getBean(beanName);创建对象
0、getBean(beanName); ioc.getBean();
1、doGetBean(name, null, null, false);
2、先获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
从private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);获取的
3、缓存中获取不到,开始Bean的创建对象流程;
4、标记当前bean已经被创建
5、获取Bean的定义信息;
6、【获取当前Bean依赖的其他Bean;如果有按照getBean()把依赖的Bean先创建出来;】
7、启动单实例Bean的创建流程;
1)、createBean(beanName, mbd, args);
2)、Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor先拦截返回代理对象;
【InstantiationAwareBeanPostProcessor】:提前执行;
先触发:postProcessBeforeInstantiation();
如果有返回值:触发postProcessAfterInitialization();
3)、如果前面的InstantiationAwareBeanPostProcessor没有返回代理对象;调用4)
4)、Object beanInstance = doCreateBean(beanName, mbdToUse, args);创建Bean
1)、【创建Bean实例】;createBeanInstance(beanName, mbd, args);
利用工厂方法或者对象的构造器创建出Bean实例;
2)、applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);
3)、【Bean属性赋值】populateBean(beanName, mbd, instanceWrapper);
赋值之前:
1)、拿到InstantiationAwareBeanPostProcessor后置处理器;
postProcessAfterInstantiation();
2)、拿到InstantiationAwareBeanPostProcessor后置处理器;
postProcessPropertyValues();
===赋值之前:=
3)、应用Bean属性的值;为属性利用setter方法等进行赋值;
applyPropertyValues(beanName, mbd, bw, pvs);
4)、【Bean初始化】initializeBean(beanName, exposedObject, mbd);
1)、【执行Aware接口方法】invokeAwareMethods(beanName, bean);执行xxxAware接口的方法
BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
2)、【执行后置处理器初始化之前】applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
BeanPostProcessor.postProcessBeforeInitialization();
3)、【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd);
1)、是否是InitializingBean接口的实现;执行接口规定的初始化;
2)、是否自定义初始化方法;
4)、【执行后置处理器初始化之后】applyBeanPostProcessorsAfterInitialization
BeanPostProcessor.postProcessAfterInitialization();
5)、注册Bean的销毁方法;
5)、将创建的Bean添加到缓存中singletonObjects;
ioc容器就是这些Map;很多的Map里面保存了单实例Bean,环境信息。。。。;
所有Bean都利用getBean创建完成以后;
检查所有的Bean是否是SmartInitializingSingleton接口的;如果是;就执行afterSingletonsInstantiated();
12、finishRefresh();完成BeanFactory的初始化创建工作;IOC容器就创建完成;
1)、initLifecycleProcessor();初始化和生命周期有关的后置处理器;LifecycleProcessor
默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;如果没有new DefaultLifecycleProcessor();
加入到容器;

		写一个LifecycleProcessor的实现类,可以在BeanFactoryvoid onRefresh();void onClose();	2)、	getLifecycleProcessor().onRefresh();拿到前面定义的生命周期处理器(BeanFactory);回调onRefresh();3)、publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成事件;4)、liveBeansView.registerApplicationContext(this);======总结===========
1)、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息;1)、xml注册bean;<bean>2)、注解注册Bean;@Service、@Component、@Bean、xxx
2)、Spring容器会合适的时机创建这些Bean1)、用到这个bean的时候;利用getBean创建bean;创建好以后保存在容器中;2)、统一创建剩下所有的bean的时候;finishBeanFactoryInitialization();
3)、后置处理器;BeanPostProcessor1)、每一个bean创建完成,都会使用各种后置处理器进行处理;来增强bean的功能;AutowiredAnnotationBeanPostProcessor:处理自动注入AnnotationAwareAspectJAutoProxyCreator:来做AOP功能;xxx....增强的功能注解:AsyncAnnotationBeanPostProcessor....
4)、事件驱动模型;ApplicationListener;事件监听;ApplicationEventMulticaster;事件派发:




















查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 2020电工(初级)证考试及电工(初级)复审模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序2020电工(初级)证考试及电工(初级)复审模拟考试,包含电工(初级)证考试答案解析及电工(初级)复审模拟考试练习。由安全生产模拟考试一点通公众号结合国家电工(初级)考试最新大纲及电工(初级)考试真题出具,有助于电工…...

    2024/4/13 22:40:19
  2. 为什么苏联打下了如此强的数学基础,俄罗斯却至今无法成为AI强国?

    作者:俄罗斯小笨笨 链接:https://www.zhihu.com/question/395842406/answer/1243718056 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。数学实力有多强我不清楚,我也对数学的了解也不专业。但是让俄罗斯无法成为AI强国的最大问题之一,肯…...

    2024/4/10 12:18:39
  3. 陕西“高山农业”-农业大健康·太白县:谋定小而美小而精

    陕西“高山农业”-农业大健康太白县:谋定小而美小而精新华社记者张斌、邵瑞 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 哲商对话 万赢信采编:“近年来,地处秦岭腹地的陕西太白县依托其海拔高、生态好等自然资源禀赋。”谋定研究~功能性…...

    2024/4/10 12:18:38
  4. 手把手的教你安装PyCharm --Pycharm安装详细教程(一)(非常详细,非常....)

    简介 Jetbrains家族和Pycharm版本划分: pycharm是Jetbrains家族中的一个明星产品,Jetbrains开发了许多好用的编辑器,包括Java编辑器(IntelliJ IDEA)、JavaScript编辑器(WebStorm)、PHP编辑器(PHPStorm)、Ruby编辑器(RubyMine)、C和C++编辑器(CLion)、.Net编辑器(…...

    2024/4/10 12:18:37
  5. python灰帽子-进程调试基础2

    承接上一篇,进程调试基础1 第二种方法:将调试附加到一个正在运行的进程。 1 - 要附加到指定的进程,需要先获得他的句柄。这个任务由OpenProcess()完成,次函数由kernel32.dll库导出。原型如下 HANDLE WINAPI OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandleDWORD dw…...

    2024/4/10 12:18:37
  6. Python 爬虫笔记整理

    文章目录python安装虚拟环境selenium基本使用1. 安装2. 基本使用3. selenium 元素定位方法4. selenium 切换浏览器窗口方法5. 实现登入功能6. cookies使用 python安装虚拟环境多工程中环境的依赖可能不同,软件包版本也可能不同,创建虚拟环境避免崩掉。安装虚拟环境包pip inst…...

    2024/4/10 12:18:35
  7. 2020-07-28

    PTA练习4-6猜数字游戏 ">//#include<stdlib.h> //#include<time.h> //猜数字游戏 /* 猜数字游戏是令游戏机随机产生一个100以内的正整数,用户输入一个数对其进行猜测。 需要你编写程序自动对其与随机产生的被猜数进行比较,并提示大了(“Too big”),…...

    2024/4/10 13:22:44
  8. 2020A证(安全员)考试题库及A证(安全员)复审模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序2020A证(安全员)考试题库及A证(安全员)复审模拟考试,包含A证(安全员)考试题库答案解析及A证(安全员)复审模拟考试练习。由安全生产模拟考试一点通公众号结合国家A证(安全员)考试最新大纲及A证(安全员)考试真题出具,有助于A证(安…...

    2024/4/10 13:22:43
  9. 人工智能的发展历史是怎样的?

    作者:小熊软糖 链接:https://www.zhihu.com/question/63117803/answer/1365903011 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。人工智能的名字诞生在1956年的达特茅斯会议上,之后1959 年系统的概念诞生。人们当时客观地认为人工智能经…...

    2024/4/13 11:35:19
  10. 浅谈iOS进阶路线

    目录 1.对本职业看法 2.学习方法 3.职业规划 4.产品公司&外包公司 5.做一个负责任的开发者 6.iOS开发学习路线 7.iOS基础知识点 8.iOS中级知识点 9.iOS高级知识点 10.官方Kit对本职业看法16年我尝试加入各种iOS开发交流群,群里的气氛大致就是:学什么iOS,iOS完了,OC完了.群里…...

    2024/4/10 13:22:41
  11. Inno Setup 6.0.0+ 繁体中文语言包

    将下面的内容复制保存为ChineseTraditional.isl文件名放入Inno Setup安装目录; *** Inno Setup version 6.0.0+ Chinese Traditional messages *** ; ; Name: John Wu, mr.johnwu@gmail.com ; Base on 5.5.3+ translations by Samuel Lee, Email: 751555749@qq.com ; Translati…...

    2024/4/10 13:22:42
  12. BUUCTF 金三胖 二维码 N种方法求解

    金三胖直接丢到PR里面去就可以慢慢看里面一闪一闪的flag了 二维码扫一扫,没东西,想到一般misc的题都喜欢塞压缩包,直接把文件名后缀改成zip,果然是的,之后用软件强行破解即可 N种方法求解,丢到winhex里面,我们可以看到有这个进程里面有base64的密文,复制下来,base64转…...

    2024/4/10 13:22:39
  13. rabbitmq之rabbitmq工作模型与Java编程(一)

    文章目录rabbitmq工作模型与Java编程一 典型应用场景二 基本介绍AMQP协议RabbitMQ的特性工作模型三种主要的交换机Direct Exchange 直连交换机Topic Exchange 主题交换机Fanout Exchange 广播交换机三 Java API编程创建Maven工程,pom.xml引入依赖生产者消费者参数说明声明交换…...

    2024/4/10 13:22:38
  14. 网络服务器如何批量自动实现NTP时钟服务工作?

    网络服务器如何批量自动实现NTP时钟服务工作? 网络服务器如何批量自动实现NTP时钟服务工作? 最近项目上新上了2台时钟设备,需要把网络内的一百多台linux服务器配置NTP服务,实现和时钟设备时间同步,为了避免每台设备挨个配置的麻烦,写了一个python脚本。 脚本分3个文件,第…...

    2024/4/10 13:22:37
  15. win10使用技巧03--通过shell脚本实现定时关机

    新建定时关机.cmd,然后编辑填入以下内容 @echo "电脑将于2分钟后关机,请注意保存数据。" # rem shutdown.exe -s -t 120 # s:秒 t:时间 # 2小时候关机举例:2*60*60=7200如果想取消执行电脑定时关机命令,新建一个脚本取消定时关机.cmd,填入以下内容 shutdown -a…...

    2024/4/10 13:22:36
  16. git和github 教程

    文章目录git 教程githubgit and github git 教程 github # 拉取代码 $ git clone url # 配置开发者用户名和邮箱 $ git config user.name name1 $ git config user.email XXX@qq.com# 添加文件到暂存区 $ git add filepath# 提交文件变动到版本库 git commit -m "关键字”…...

    2024/4/17 0:33:39
  17. 体制内必须要懂的道理77条

    1. 领导说“研究研究”,不要傻等,是要看你表现咋样。机关处处是机关,即使是你亲眼所见的也未必是事情的真相,凡事都要走心过脑,打个盹也别忘睁开半只眼。2. 最忌讳虚张声势,真正有关系的人从来不多言,不要小看身边的每个人,踩着你上位的往往就是其中最不起眼的那个。3.…...

    2024/4/11 22:06:52
  18. day06:02oracle体系结构_存储结构

    一 : 存储结构1、逻辑结构段、区、块Segments/Extents/DataBlocks从存储的角度只有段记录到数据字典创建段表空间 tablespace表空间是数据库的最大逻辑存储结构,和物理数据文件相对应,一个表空间可以由多个数据文件组成,一个数据文件只能属于一个表空间主要的几个表空间:S…...

    2024/4/10 13:22:33
  19. 链表专题

    链表专题 链表翻转 //递归链表反转 public ListNode reverseList(ListNode head) {if(head == null || head.next == null) return head;ListNode last = reverseList(head.next);head.next.next = head;head.next = null;return last;}//迭代链表反转 public ListNode reverse…...

    2024/4/10 13:22:32
  20. vue-query-builder获取sql

    Vue版的query builder。可用于前端构造查询条件,类似jQuery Builde的简易版。 源地址:https://github.com/dabernathy89/vue-query-builder 由于作者比较纠结是否应该在前端进行sql转化而没有加这个功能😂,所把它搬过来简单的加上了将json条件转化为sql的功能。 修改后:h…...

    2024/4/10 13:22:31

最新文章

  1. 异步 IO 机制 io_uring

    一、io_uring 原理 如何解决频繁 copy 的问题 → mmap 内存映射解决。 submit queue 中的节点和 complete queue 中的节点共用一块内存&#xff0c;而不是把 submit queue 中的节点 copy 到 complete queue 中。 如何做到线程安全 → 无锁环形队列解决。 二、io_uring 使用 内…...

    2024/4/20 8:01:18
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. HarmonyOS 开发-一镜到底“页面转场”动画

    介绍 本方案做的是页面点击卡片跳转到详情预览的转场动画效果 效果图预览 使用说明 点击首页卡片跳转到详情页&#xff0c;再点击进入路由页面按钮&#xff0c;进入新的路由页面 实现思路 首页使用了一种视觉上看起来像是组件的转场动画&#xff0c;这种转场动画通常是通过…...

    2024/4/18 23:18:44
  4. axios拦截器:每次请求自动带上 token

    Step 1&#xff1a;创建Axios实例并添加拦截器 在你的Vue项目中&#xff0c;一般我们会先导入axios&#xff0c;然后创建一个axios实例。这样做是为了方便统一管理和配置。 import axios from axios; // 引入axios// 创建一个axios实例 const service axios.create();// 添加请…...

    2024/4/18 9:13:14
  5. #QT项目实战(天气预报)

    1.IDE&#xff1a;QTCreator 2.实验&#xff1a; 3.记录&#xff1a; &#xff08;1&#xff09;调用API的Url a.调用API获取IP whois.pconline.com.cn/ipJson.jsp?iphttp://whois.pconline.com.cn/ipJson.jsp?ip if(window.IPCallBack) {IPCallBack({"ip":&quo…...

    2024/4/18 20:00:55
  6. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/4/19 19:02:10
  7. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/4/19 11:51:49
  8. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/4/19 11:33:34
  9. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/4/19 11:52:08
  10. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/4/19 2:38:12
  11. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/4/20 7:01:14
  12. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/4/19 11:52:49
  13. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/4/19 18:52:15
  14. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/4/19 23:08:02
  15. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/4/20 0:22:23
  16. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/4/19 23:04:54
  17. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/4/20 1:12:38
  18. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/4/19 3:53:57
  19. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/4/19 19:50:16
  20. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/4/20 1:43:00
  21. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/4/19 11:54:11
  22. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/4/19 23:35:17
  23. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/4/19 10:00:05
  24. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/4/20 6:45:17
  25. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/4/20 3:28:04
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57