什么是 Spring?为什么学它?

前言

欢迎来到本篇文章!在这里,我将带领大家快速学习 Spring 的基本概念,并解答两个关键问题:什么是 Spring,以及为什么学习 Spring。

废话少说,下面,我们开始吧!

Spring 官方文档:http://docs.spring.io/spring-framework/docs/5.2.24.RELEASE/spring-framework-reference/

image-20230523222649313

为什么需要学习 Spring?

  1. 简化我们的企业级应用程序的开发,提升我们的开发效率。
  2. 学 Java 的路上不得不学 Spring,不学直接用 Spring Boot 是可以,开箱即用,但是很难学懂,可能只是会用,不能知其然而知其所以然。
  3. 面试会问的啊!工作会用的啊!所以需要学嘛!OK!

Spring 这个词,指的是什么?

Spring 这个术语在不同的上下文中有不同的含义。它可以用来指代 Spring Framework 项目本身,这是梦开始的地方。

后来随着时间的推移,其他基于 Spring Framework 构建的项目也相继出现。当人们说 Spring 时,通常指整个项目家族。不过,在本系列中,我们就只指代它本身,即 Spring Framework 本身。

Spring Framework 被分为多个模块,应用程序可以选择需要哪些模块。核心容器模块包括配置模型和依赖注入机制等内容。除此之外,Spring Framework 还为不同类型应用架构提供了基础支持,包括消息传递、事务数据和持久化以及 Web 开发等领域,并且同时提供了基于 ServletSpring MVC Web 框架和并行运行的 Spring WebFlux 响应式 Web 框架。

Spring 的模块

实际上,Spring Framework 大约由 20 个模块组成。这些模块分为核心容器、数据访问/集成、Web、AOP(面向切面编程)、仪表板、消息和测试等。如官网上给出的这张图所示:

spring overview

Core Container(核心模块)

当我们谈论 Spring 的核心容器时,我们指的是一些模块,它们共同构成了这个框架的基础。这些模块包括 spring-corespring-beansspring-contextspring-context-supportspring-expression

首先,让我们来了解一下 spring-corespring-beans 模块。它们提供了一些基本功能,其中最重要的是「IoC(控制反转)」和「依赖注入」。简单来说,IoC 允许我们将对象的创建和管理交给框架来处理,而不是我们自己手动创建和管理。依赖注入则是一种将对象之间的依赖关系注入到它们之间的过程,这样可以实现对象之间的解耦。

另外,BeanFactory 是一个工厂模式的复杂实现,它的作用是消除编写单例模式的需要,并且允许我们将对象的配置和规范与实际的程序逻辑分离开来。

接下来是 Contextspring-context)模块,它是在 CoreBeans 模块的基础上构建的。Context 模块提供了一种类似于 JNDI(Java命名和目录接口)注册表的方式来访问对象。除了继承 Beans 模块的功能外,Context 模块还添加了对国际化、事件传播、资源加载等功能的支持。它还能够通过 Servlet 容器等方式透明地创建上下文。此外,Context 模块还支持一些 Java EE 特性,如 EJB(企业级 Java Bean)、JMX(Java管理扩展)和基本的远程处理。在 Context 模块中,ApplicationContext 接口是重点关注的对象。另外,spring-context-support 模块为将常见的第三方库集成到 Spring 应用程序上下文中提供了支持,尤其是在缓存(EhCache、JCache)和调度(CommonJ、Quartz)方面。

最后,我们有 spring-expression 模块,它提供了一个强大而灵活的表达式语言,用于在运行时查询和操作对象图(object graph)。该语言是 JSP 2.1 规范中统一表达式语言(unified EL)的扩展。它支持设置和获取属性值、属性赋值、方法调用、访问数组、集合和索引器的内容,以及逻辑和算术运算符、命名变量等。通过 Spring IoC 容器,我们还可以按名称检索对象。此外,该表达式语言还支持列表投影、选择和常见的列表聚合操作。

AOP 和 Instrumentation

spring-aop 模块是 Spring 框架中用于实现面向切面编程的一部分,它遵循 AOP Alliance 标准。

那么什么是面向切面编程呢?简单来说,它允许我们在代码中定义方法的拦截器和切入点,从而将某些功能与实际业务逻辑分离开来,以实现更清晰的代码结构和更好的模块化。举个例子,比如当我们需要在代码中引入一些日志记录、安全性检查、性能监控的代码,那么这些代码就是横切关注点,我们可以使用 AOP 来实现这些代码的引入,而不是将这些代码分散到各个业务逻辑中。通过使用 AOP,我们可以将这些通用的横切关注点定义为切面,并将它们应用到适当的方法上,从而实现代码的解耦和重用。

此外,Spring 还提供了单独的 spring-aspects 模块,用于与 AspectJ 进行集成。AspectJ 是一个功能强大的 AOP 框架,通过与 Spring 的集成,我们可以利用 AspectJ 的更高级功能来实现更复杂的切面编程。

另外还有一个模块叫做 spring-instrument,它提供了类仪表化(instrumentation)的支持和类加载器实现,在某些应用服务器中可以使用。这个模块的作用是提供一些工具和机制,以便在运行时对类进行修改和增强,从而实现一些特定的需求。例如,spring-instrument-tomcat 模块是针对 Tomcat 服务器的特定实现,它提供了用于仪表化的代理机制。

Messaging

Spring 4 引入了一个名为 spring-messaging 的模块,它包含了 Spring Integration 项目的核心抽象,例如 MessageMessageChannelMessageHandler 等等。这个模块的目的是提供消息传递应用程序的基础支持。

通过 spring-messaging 模块,我们可以构建基于消息传递的应用程序,其中不同组件之间通过消息进行通信。以下是一些关键概念和功能:

  1. Message消息是应用程序中传递的数据单元。它可以包含有关消息内容和元数据的信息。
  2. MessageChannel消息通道是消息在应用程序中传递的路径。它充当发送者和接收者之间的中介。
  3. MessageHandler消息处理器是负责接收和处理消息的组件。它可以执行特定的业务逻辑或转发消息给其他组件。

spring-messaging 模块还引入了一组注解,用于将消息映射到方法,类似于 Spring MVC 中基于注解的编程模型。这使得我们可以通过简单的注解来定义消息的处理方式,让代码更加清晰和易于理解。

Data Access/Integration

当我们处理数据时,Spring 的数据访问/集成层提供了一些模块,以帮助我们更轻松地与数据库和其他数据源进行交互。

  • spring-jdbc 模块简化了与数据库进行交互的过程。它提供了一个抽象层,让我们可以使用更简单、更易于理解的代码来执行数据库操作,而不必处理繁琐的细节。
  • spring-tx 模块支持事务管理。事务是用来确保数据的一致性和完整性的机制。使用 Spring 的事务管理模块,我们可以以编程式或声明式的方式来管理事务,从而更轻松地处理数据的变化和操作。
  • spring-orm 模块提供了与对象关系映射(ORM)框架的集成。ORM 是一种将数据库中的数据映射到对象的技术,它使得我们可以使用面向对象的方式来操作数据库。通过使用 Spring 的 ORM 模块,我们可以方便地集成流行的 ORM 框架(如 Hibernate、MyBaits),并结合 Spring 的其他功能,例如简单的声明式事务管理。
  • spring-oxm 模块提供了对象和 XML 之间的映射支持。它可以帮助我们将 Java 对象转换成 XML 格式,或者将 XML 转换回 Java 对象。这对于处理与 XML 相关的数据非常有用。
  • spring-jms 模块用于处理 Java 消息服务(Java Message Service)。它提供了生成和消费消息的功能。从 Spring Framework 4.1 版本开始,它还与 spring-messaging 模块进行了集成,使得基于消息传递的应用程序开发更加方便。

Web

Web 层由 spring-webspring-webmvc 等模块组成。

  • spring-web 模块提供了基本的 Web 功能。它包含处理 MultipartFile 上传使用 Servlet 监听器进行初始化 IoC 容器的功能。该模块还包含与Web相关的部分,如 HTTP 客户端Spring 远程支持,以便与其他Web服务进行通信。
  • spring-webmvc 模块(也称为Web-Servlet模块)是 Spring 框架中用于构建 Web 应用程序的重要模块。它实现了 Model-View-Controller(MVC)架构和 RESTful Web 服务。使用 Spring MVC,我们可以将业务逻辑代码和 Web 表单清晰地分离,实现更好的代码组织和可维护性。该模块与 Spring 的其他功能无缝集成,使我们能够轻松地使用依赖注入、事务管理等功能来构建灵活和可扩展的Web应用程序。

Test

spring-test 模块支持使用 JUnit 或 TestNG 对 Spring 组件进行单元测试和集成测试,它提供了一致的 Spring ApplicationContext 加载和缓存机制,并提供了 Mock 对象,便于我们进行测试。

Spring 的历史

Spring 框架于 2003 年诞生,是对早期 J2EE 规范复杂性的回应。虽然有些人认为 Java EE 和 Spring 存在竞争关系,但实际上,Spring 与 Java EE 相辅相成。Spring 编程模型并不包含 Java EE 平台规范;相反,它集成了来自 EE 大伞下精心挑选的个别规范:

  • Servlet API(JSR 340)

  • WebSocket API(JSR 356)

  • Concurrency Utilities(JSR 236)

  • JSON Binding API(JSR 367)

  • Bean Validation(JSR 303)

  • JPA(JSR 338)

  • JMS (JSR914),以及必要时用于事务协调的 JTA/JCA 设置。

Spring 框架还支持依赖注入(JSR330)和常见注解(JSR250)规范,我们开发人员可以选择使用这些规范而非由 Spring 框架提供的特定机制。

从 Spring Framework 5.0 开始,Spring 要求 Java EE 7 级别(例如 Servlet 3.1+,JPA 2.1+)作为最低要求,同时在运行时提供与 Java EE 8 级别的新API(例如 Servlet 4.0、JSON Binding API)的开箱即用集成。这使得 Spring 完全兼容 Tomcat 8 和 9、WebSphere 9 以及 JBoss EAP 7 等服务器。

随着时间推移,在应用程序开发中 Java EE 的角色也在不断演变。在 Java EE 和 Spring 的早期,应用程序是为部署到应用服务器而创建的。如今,在 Spring Boot 的帮助下,应用程序以 devops 和云友好的方式创建,Servlet 容器被嵌入其中并且易于更改。从 Spring Framework5 开始,WebFlux 应用程序甚至不直接使用 Servlet API,并且可以运行在非 Servlet 容器(例如 Netty )上。

Spring 继续创新和发展。除了 Spring Framework 之外,还有其他项目,例如 Spring Boot、Spring Security、Spring Data、Spring Cloud、Spring Batch 等等。

Spring 设计理念

当你学习一个框架时,了解它所做的事情以及遵循的原则同样重要。以下是 Spring Framework 的指导原则:

  • 在每个层面提供选择:Spring 允许我们尽可能地推迟设计决策。例如,我们可以通过配置切换应用程序所连接的数据库而无需更改代码。对于许多其他基础设施问题和第三方API的集成也是如此。

  • 容纳不同的观点:Spring 非常灵活,没有固定的方式来解决应用程序的需求。它提供了多种方法来完成相同的任务,以适应不同开发者的不同观点和需求。

  • 保持强大的向后兼容性:Spring Framework 的设计经过精心考虑,尽量减少对你已有代码的影响。这意味着当我们升级到新的版本时,我们的应用程序仍然可以正常运行,而无需担心因为框架更新而导致问题。Spring 还支持多个 Java 开发工具包(JDK)版本和第三方库,这样你可以继续使用 Spring 来开发和维护你的应用程序。

  • 关注 API 设计:Spring 团队花费了大量的时间和精力来设计直观易懂、稳定可靠的 API。他们努力确保 API 在多个版本和多年的时间跨度中保持一致性,这样我们就可以更轻松地理解和使用它们。

  • 确立高标准代码质量:Spring Framework 强调清晰、准确的文档注释。它是少数几个代码结构清晰且包之间没有循环依赖关系的项目之一。这种高标准的代码质量有助于提高框架的可维护性和可扩展性。

所以什么是 Spring?

Spring 是一个轻量级的、开源的 Java 框架,实现了 IoC(Inversion of Control)和 AOP(Aspect Oriented Programming)等功能。

在 Spring 的官网介绍中,Spring 被描述为「构建企业级应用程序的一站式框架」,它提供了如下的优点:

  • 便于开发:Spring 的组件化和松耦合的特性使得开发变得更加简单,开发者可以更加专注于业务逻辑的实现。
  • 便于测试:Spring 的代码结构和依赖注入机制使得测试变得更加容易。
  • 便于集成:Spring 的可插拔的架构,使得其可以方便地与其他框架和组件进行集成。
  • 便于部署:Spring 应用程序的部署非常简单,开发者只需要将应用程序打成 war 包,然后将其部署到支持 Java 应用程序的服务器上即可。

Spring 框架包含了如下的模块:

  • 核心容器(Core Container):包括 IoC 和 DI(Dependency Injection,依赖注入)、事件、资源、国际化、验证、数据绑定、类型转换、SpEL 和 AOP 等核心功能。
  • AOP:支持面向切面编程。
  • 工具(Instrumentation):提供了一系列的工具和支持,如 JMS、JCA、JMX、电子邮件、任务调度和缓存等。
  • 数据访问/集成(Data Access/Integration):包括对 JDBC、ORM 框架(如 Hibernate、MyBatis)事务处理,DAO 等的支持。
  • Web:包括对 Web 应用程序开发的支持,如 Spring MVC 和 Spring WebFlux 网络框架等。
  • 测试(Test):包括对 JUnit、TestNG 等的支持。

没有 Spring 和有 Spring 的区别

那到底是怎样简化了呢?体现在哪里呢?下面,为了直观展示 Spring 是如何简化我们开发的过程的,将写一个代码示例,让大家看看是怎样的区别。

对象管理

当没有 Spring 时,Java EE 开发的主要方式是使用 JSP、Servlet 和 EJB 等技术。你想一想,刚开始学习 JSP 的时候,是不是这样,没有任何框架,纯纯自己操作所有东西。

对于系统中多个对象之间的关系,没有 Spring 的时候,我们需要手动创建和管理对象之间的依赖关系

这句话可能初学者不是很好理解,我举个例子。

这里有两个设计好的系统中的两个类,Employee 和 Department(用于描述员工以及部门信息的类)。

Employee.java:

public class Employee {
    private int id;
    private String name;
    private Department department;
    
    // 省略 getter 和 setter
}

Department.java:

public class Department {
    private int id;
    private String name;
    
    // 省略 getter 和 setter
}

未使用 Spring 的时候

我们现在的业务假设是需要打印员工的部门信息,那么我们就需要手动管理它们之间的依赖关系的,代码如下:

public class Main {
    public static void main(String[] args) {
        Department department = new Department(1, "Just do IT");
        Employee employee = new Employee(1, "god23bin", department);
        System.out.println(employee.getDepartment().getName());
    }
}

你创建一个 Employee 对象,就必须自己再去创建一个 Department 对象(因为 Employee 对象依赖于 Department 对象),并将 Department 对象给关联到 Employee 对象上。是吧。现在,我相信屏幕前的你已经懂了所谓的手动创建和管理对象之间的依赖关系了。

使用 Spring 的时候

当你使用 Spring 的时候,就完全不需要这么做。依然是这个例子,现在我使用 Spring 来操作,对象的管理就交给 Spring 处理,来看看我怎么写的:

@Configuration
public class AppConfig {
    
    @Bean
    public Department department() {
        return new Department(1, "Just do IT");
    }
    
    @Bean
    public Employee employee() {
        return new Employee(1, "god23bin", department());
    }
    
}

我写了一个 AppConfig 类,在类上使用了一个 @Configuration 注解,表示这是一个配置类。

接着,写了两个方法,分别返回了一个员工对象和一个部门对象,而且在方法上使用了一个 @Bean 注解,表示这个方法返回的对象是交给 Spring IoC 进行管理的。

这两个对象都是通过调用构造方法来创建的,其中 Department 对象则被注入到了 Employee 对象中。(注入,你就理解成 setXxx 方法)

在最上面进行介绍的时候,有一个概念,就是「容器」,这个容器人们也习惯称「Ioc 容器」,实际上就是 Spring 用来存放与管理应用程序中所有交给它的对象的。

现在在这个容器中,就有 Department 对象和 Employee 对象。

我们的业务依旧是打印员工的部门信息,此刻,我们只需要从「容器」中获取我们需要的对象就可以了,直接获取员工对象,不用手动自己 new 一个员工对象,也不需要自己 new 一个部门对象了。

我们通过 AnnotationConfigApplicationContext 来加载配置类 AppConfig,然后通过 getBean 方法来获取 Employee 对象,此过程 Spring 完成了依赖注入的效果,Employee 对象是具有 Department 对象的。

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Employee employee = context.getBean(Employee.class);
        System.out.println(employee.getDepartment().getName());
    }
}

不过,实际上,我们在真正的项目中,并不会这样去使用,即不会去手动写 context.getBean() 等这些代码,而是直接通过依赖注入的方式,这个后面再写咯。现在知道是怎么回事就 OK 啦!

当然,由于篇幅有限,可能目前你还没能理解这样做有什么好处,可能会有各种疑惑,没关系,慢慢学习下去就会迎刃而解了。

其他的管理

在没有 Spring 时,我们需要在代码中手动处理一些与业务逻辑无关的问题,比如连接池和事务管理等。而有了 Spring 之后,这些问题都可以通过 Spring 的 API 和组件来解决,从而使代码更加简洁易读。

总结

Spring 是一个很牛的、开源的 Java 框架,实现了 IoC(Inversion of Control,控制反转)和 AOP(Aspect Oriented Programming,面向切面编程)等功能。

Spring 的核心特点包括便于开发、便于测试、便于集成和便于部署,啥都方便。

Spring 框架的出现简化了 Java EE(Enterprise Edition)开发的过程。在没有使用 Spring 的情况下,开发 Java EE 应用程序需要手动创建和管理对象之间的依赖关系,而使用 Spring 可以通过配置和注解来实现对象的自动管理和依赖注入。Spring 还提供了许多其他模块和功能,如数据访问/集成、Web 开发支持、AOP、工具等,使开发人员可以更加便捷地开发企业级应用程序。

总之,学习 Spring 可以帮助我们更好地理解和应用现代企业级 Java 开发的基本概念和最佳实践,提高开发效率和代码质量。

参考

http://docs.spring.io/spring-framework/docs/5.0.0.RC3/spring-framework-reference/overview.html#spring-introduction

http://docs.spring.io/spring-framework/docs/5.2.24.RELEASE/spring-framework-reference/overview.html#overview

最后的最后

希望各位屏幕前的靓仔靓女们给个三连!你轻轻地点了个赞,那将在我的心里世界增添一颗明亮而耀眼的星!

咱们下期再见!

本文转载于网络 如有侵权请联系删除

相关文章

  • 《JavaScript 模式》读书笔记(8)— DOM和浏览器模式1

    大家好,又见面了,我是你们的朋友全栈君。  在本书的前面章节中,我们主要集中关注于核心JavaScript(ECMAScript),而并没有太多关注在浏览器中使用JavaScript的模式。本章将探索一些浏览器特定的模式,因为浏览器是使用JavaScript最为常见的环境。同时也是很多人不喜欢使用JavaScript的原因,他们认为JavaScript只是一种浏览器脚本。考虑到在浏览器中存在很多前后矛盾的主机对象和DOM实现,这种想法也是可以理解的。很明显通过使用一些较好的可以减少客户端脚本负担的实践技巧,可以获益颇多。  在本章您将看到模式被划分为几类,包含DOM脚本、事件处理、远程脚本、页面载入JavaScript的策略和在产品网站上配置JavaScript的步骤等。  但是首先,让我们简单的从哲学角度来探索如何处理客户端的脚本。一、关注分离在网站应用程序的开发过程中主要关心如下三个内容:内容(Content):HTML的文档。表现(Presentation):指定文档外观的CSS样式。行为(Behavior):处理用户交互和文档各种动态变化的JavaScript。  将这三部分尽

  • AIX系统镜像(RAID1)制作和故障恢复

    AIX系统镜像(RAID1) 对操作系统做镜像,防止硬盘坏掉时,不影响系统正常运行,起到容灾的作用。 制作rootvg的标准步骤 1. extendvg 2. chvg–Qn 3. mirrorvg–s 4. syncvg–v 5. bosboot–a 6. bootlist 7. shutdown–Fr 8. bootinfo–b 1.首先将1个空闲的物理磁盘加入到rootvg中,例如:hdisk1. #extendvgrootvghdisk1 如果vg中仅包含2个pv(如:hdisk0,hdisk1),且1个pv是另1个pv的镜像,称为单镜像(singlemirroring),那么QUORUM是不需要的,请执行该命令关闭它. #chvg–Qnrootvg 此情况称之为单镜像(singlemirroring),一般单镜像的卷组都需要将quorum关闭,否则卷组中拥有2份VGDA的磁盘不可用时,受quorum制约,整个卷组无法激活,从而失去镜像意义. 对于rootvg镜像更加需要关闭quorum,否则一旦包含2份VGDA的磁盘不可用时,系统在引导过程中将不能激活rootvg,从而引起启

  • 5月腾讯云容器产品技术月报|容器给大小儿童发礼物啦~

    2022年5月VOL:25腾小云告诉你最前线的产品新特性,总有一款让你心动~云说新品容器产品新特性5月上新腾讯云容器服务公有版TKE高可扩展和高性能容器管理服务腾讯云容器服务(TencentKubernetesEngine,TKE)是高度可扩展的高性能容器管理服务,您可以在托管的云服务器实例集群上轻松运行应用程序。TKE集群支持 Kubernetes 1.22 版本 (白名单体验中)‍‍‍扩展组件Addon支持组件升级CBS/CFS/COS-CSI组件支持在创建时设置污点容忍TKE提供审计/日志/事件相关云API接口增强型云硬盘(HSSD)数据盘支持设置额外性能通过日志组件创建日志Topic时自动继承集群侧云标签现有虚拟节点功能升级为“超级节点”,全托管节点,使用更便宜腾讯云弹性容器服务EKS安全稳定的无服务器Kubernetes服务弹性容器服务(ElasticKubernetesService,EKS)是腾讯云容器服务推出的无须用户购买节点即可部署工作负载的服务模式。全新推出超级节点概念,即将上线包年包月超级节点产品能力EKSGPU服务支持创建A10机型的PodEKS 支持静态创建C

  • php设计模式之策略模式应用案例详解

    本文实例讲述了php设计模式之策略模式应用。分享给大家供大家参考,具体如下:策略模式定义:策略模式定义一系列的算法,将每个算法封装起来,并让它们可以相互装换。策略模式让算法独立于使用它的客户而独立变化。角色分析:抽象策略角色:策略类,通常由一个接口或者抽象类实现;具体策略角色:包装了相关的算法和行为;环境角色:持有一个策略类的引用,最终给客户端用。应用场景:多个类只区别在表现行为不同,可以使用策略模式,在运行的时动态选择具体要执行的行为。需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其他方式来实现。对客户隐藏具策略(算法)的实现细节,彼此完全独立。代码实现:<?php /** *CreatedbyPhpStorm. *Author:zhaorui *Date:2019/2/27 *Time:10:55 */ header('Content-Type:text/html;charset=utf-8'); //抽象策略接口 abstractclassStrategy{ abstractfunctionwayToSchool(); } //具体策略角

  • Android viewpager无限轮播获取网络图片功能

    本文实例为大家分享了viewpager无限轮播获取网络图片的具体代码,供大家参考,具体内容如下话不多说直接上代码,你们都懂的小圆点属性dot_focused.xml<?xmlversion="1.0"encoding="utf-8"? <shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle" <solidandroid:color="#f00"/ <cornersandroid:radius="8dp"/ </shape复制dot_normal.xml<?xmlversion="1.0"encoding="utf-8"? <shapexmlns:android="http://schemas.android.com/apk/res/android"

  • 存储器层次结构介绍

    存储器层次结构这里先说一下存储器系统: 寄存器----->高速缓存----->主存储 存储器对程序的性能有着巨大的影响,程序的运行就是对数据的不停的计算和搬移,其中最为耗时的就是程序对数据的搬移。因此,存储器对数据的存取速度是至关重要的。 CPU在访问寄存器中的数据只需要一个周期就可以访问到,在高速缓存中需要4-75个周期,如果在主存器上则需要上百个周期,如果在磁盘上则需要几千万个周期。 如果你理解了系统是如何将数据在存储器结构层次中上上下下移动的,你就可以编写自己的应用程序,使它们的数据存储在较高层次结构的地方,在那里CPU能更快的访问。先展示出这篇文章的结构图:随机访问存储器 静态RAM静态RAM(SRAM)将一个位存储在一个双稳态的存储器单元里面,每个单元由6个晶体管组成。 SRAM得存储单元具有双稳态特性。只要有电,它就会永远的保存它的值,即使有干扰来扰乱电压,当干扰消除之后,电路就会恢复到稳定值。动态RAM动态RAM(DRAM)将每个位存储为对一个电容充电,电容小到30毫微法拉的电容。DRAM造的非常密集,每个单元由一个电容和一个访问晶体管组成。 DRAM存储单元

  • Android精通:TableLayout布局,GridLayout网格布局,FrameLayout帧布局,AbsoluteLayout绝对布局,RelativeLayout相对布局

    标题图在Android中提供了几个常用布局:LinearLayout线性布局RelativeLayout相对布局FrameLayout帧布局AbsoluteLayout绝对布局TableLayout表格布局GridLayout网格布局TableLayout表格布局TableLayout表格布局.pngTableLayout的介绍TableLayout是将子类向分别排列成行和列的布局视图容器,TableLayout是由许多TableRow对象组成的,表格布局以行列的形式管理子控件,每一个单元是一个TableRow或者View对象。在TableLayout中可以通过setConlumnShrinkable()或setConlumnStretchable()方法来指定某些列为可以缩小或可伸缩,列是从0开始计数的,第一列为0。属性常用的几种属性:stretchColumns为设置运行被拉伸的列的序号,如android:stretchColumns="2,3"表示在第三列的和第四列的一起填补空白,如果要所有列一起填补空白,则用“*”符号,列号都是从0开始算的。shrinkCo

  • resize失败原因调查

    对云主机进行resize操作没有成功对一个vm做resize,即从一个小的flavor换一个大的flavor,没有成功检查云主机所在节点的nova-compute.log2017-07-0317:50:08.57324296TRACEoslo_messaging.rpc.dispatcherFile"/usr/lib/python2.7/site-packages/nova/compute/manager.py",line6959,in_error_out_instance_on_exception 2017-07-0317:50:08.57324296TRACEoslo_messaging.rpc.dispatcherraiseerror.inner_exception 2017-07-0317:50:08.57324296TRACEoslo_messaging.rpc.dispatcherResizeError:Resizeerror:notabletoexecutesshcommand:Unexpectederrorwhilerunningcommand. 2

  • 关于FindWindow函数「建议收藏」

    大家好,又见面了,我是你们的朋友全栈君。在调用FindWindow函数的时候,应该第一个参数为空,第二个参数为窗口的标题名。classname是窗口在创建时的注册名称,不是源代码的类名,通常可以不指定,除非确切地知道。另外,vs自带一个spy++的工具,可以探查当前所有窗口的信息,包括注册类名。FindWindow这个函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串。这个函数有两个参数,第一个是要找的窗口的类,第二个是要找的窗口的标题。在搜索的时候不一定两者都知道,但至少要知道其中的一个。拿窗口句柄FindWindow是最简单的但如果用类名找不到,只能使用FindWindowEx或者直接EnumWindow来做,优先推荐是去枚举[DllImport(“user32.dll”,EntryPoint=“FindWindow”,SetLastError=true)] privatestaticexternIntPtrFindWindow(stringlpClassName,stringlpWindowName);[DllImport(“user32.dll”,EntryPoint=“Fi

  • 今年国家信创采购龙芯CPU近乎为零?官方回应:处于项目交接期

    近几年,国产半导体芯片高速发展,国家信创采购也在加大对国产芯片的扶持力度。9月26日,有投资者向龙芯中科提问称,“公司作为自主性最高的国产CPU企业,在今年信创领域计算机采购中却面临着近乎出局的局面,对信创这个国家战略实在是莫大的讽刺,请问对于而引进国外技术、严重依赖国外授权的兆芯、飞腾却占据了绝大多数信创份额的情形,公司计划如何应对?”对此,龙芯中科回应称:“今年总体处于项目交接期,桌面批量采购确实比较少。上半年公司信息化业务同比有大幅度下降,而竞品x86产品在信创市场的比例确实有提升,但‘近乎出局’的说法还是有失偏颇。国家战略方向是无比正确的,但政策的落地以及执行是需要过程的。”龙芯中科认为,自主化替代应该是体系的替代,而不仅仅是产品的替代,但事物的发展,包括人们的认知,和龙芯的发展一样都是波浪式发展、螺旋式上升的,请给予一定的时间和耐心。龙芯中科强调,公司坚持自主研发,一直致力于构建自主可控的信息技术体系和产业生态。公司的战略长期以来没有改变,前途是光明的,但道路是曲折的。不仅要撸起袖子加油干,还得耐着性子坚持干。产品方面,龙芯3A5000+7A2000的组合已经推出,提高了整机

  • MIIMDIO接口详解

      本文主要分析MII/RMII/SMII,以及GMII/RGMII/SGMII接口的信号定义,及相关知识,同时本文也对RJ-45接口进行了总结,分析了在10/100模式下和1000M模式下的设计方法。  MII接口提供了MAC与PHY之间、PHY与STA(StationManagement)之间的互联技术,该接口支持10Mb/s与100Mb/s的数据传输速率,数据传输的位宽为4位。  提到MII,就有可能涉及到RS,PLS,STA等名词术语,下面讲一下他们之间对应的关系。所谓RS即Reconciliationsublayer,它的主要功能主要是提供一种MII和MAC/PLS之间的信号映射机制。  RS与MII之间的关系如下图:  MII接口的ManagementInterface可同时控制多个PHY,802.3协议最多支持32个PHY,但有一定的限制:要符合协议要求的connector特性。所谓ManagementInterface,即MDC信号和MDIO信号。前面已经讲过RS与PLS的关系,以及MII接口连接的对象。它们是通过MII接口进行连接的,示意图如下图。由图可知,MII的M

  • 腾讯云物联网边缘计算平台编辑draco设备信息api接口

    1.接口描述接口请求域名:iecp.tencentcloudapi.com。 编辑draco设备信息 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:ModifyEdgeDracoNode。 Version 是 String 公共参数,本接口取值:2021-09-14。 Region 否 String 公共参数,本接口不需要传递此参数。 EdgeUnitId 是 Integer 边缘单元ID NodeId 是 Integer 边缘节点ID NodeInfo 否 DracoNodeInfo 节点信息 IsReset 否 Boolean 是否重置draco设备 3.输出参数 参数名称 类型 描述 Reques

  • 缓存更新的套路

    摘自:https://coolshell.cn/articles/17416.html 看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。 我不知道为什么这么多人用的都是这个逻辑,当我在微博上发了这个贴以后,我发现好些人给了好多非常复杂和诡异的方案,所以,我想写这篇文章说一下几个缓存更新的DesignPattern(让我们多一些套路吧)。 这里,我们先不讨论更新缓存和更新数据这两个事是一个事务的事,或是会有失败的可能,我们先假设更新数据库和更新缓存都可以成功的情况(我们先把成功的代码逻辑先写对)。 更新缓存的的DesignPattern有四种:Cacheaside,Readthrough,Writethrough,Writebehindcaching,我们下面一一来看一下这四种Pa

  • MXNet的新接口Gluon

    为什么要开发Gluon的接口 在MXNet中我们可以通过Sybmol模块来定义神经网络,并组通过Module模块提供的一些上层API来简化整个训练过程。那MXNet为什么还要重新开发一套Python的API呢,是否是重复造轮子呢?答案是否定的,Gluon主要是学习了Keras、Pytorch等框架的优点,支持动态图(Imperative)编程,更加灵活且方便调试。而原来MXNet基于Symbol来构建网络的方法是像TF、Caffe2一样静态图的编程方法。同时Gluon也继续了MXNet在静态图上的一些优化,比如节省显存,并行效率高等,运行起来比Pytorch更快。 更加简洁的接口 我们先来看一下用Gluon的接口,如果创建并组训练一个神经网络的,我们以mnist数据集为例: importmxnetasmx importmxnet.ndarrayasnd frommxnetimportgluon importmxnet.gluon.nnasnn 复制 数据的读取 首先我们利用Gluon的data模块来读取mnist数据集 deftransform(data,label): returnd

  • jQueryEasyUI

    jQueryEasyUI是一组基于jQuery的UI插件集合体,而jQueryEasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂的javascript,也不需要对css样式有深入的了解,开发者需要了解的只有一些简单的html标签。 特点 jQueryEasyUI为提供了大多数UI控件的使用,如:accordion,combobox,menu,dialog,tabs,validatebox,datagrid,window,tree等等。 jQueryEasyUI是基于JQuery的一个前台ui界面的插件,功能相对没extjs强大,但页面也是相当好看的,同时页面支持各种themes以满足使用者对于页面不同风格的喜好。一些功能也足够开发者使用,相对于extjs更轻量。 jQueryEasyUI有以下特点: 1、基于jquery用户界面插件的集合 2、为一些当前用于交互的js应用提供必要的功能 3、EasyUI支持两种渲染方式分别为javascript方式(如:$('#p').panel({...}))和html标记方式(如:class=

  • 上升沿 下降沿 小结

    概述 电平 数字电路中,把电压的高低用逻辑电平来表示。 高低电平 逻辑电平包括高电平和低电平这两种。 高低电平的定义 不同的元器件形成的数字电路,电压对应的逻辑电平也不同。 在TTL门电路中: 把大于3.5伏的电压规定为逻辑高电平,用数字1表示; 把电压小于0.3伏的电压规定为逻辑低电平,用数字0表示。 上升沿和下降沿 数字电平从0变为1的那一瞬间叫作上升沿,从1到0的那一瞬间叫作下降沿 ============================= 详述与图示 上升沿详述 某个点的电位由低电位变成高电位的瞬间,采集的一个点动动作。 例如你有一个带自锁的DC36V的接触器,当接触器启动时,电压一下子从0V变为36V,并且一直处于36V接通状态! 但上升沿只是在接触器接通的瞬间(一个扫描周期),接通一下,然后就断开了。 差不多相当于接通瞬间的点动按钮。 图示:0-1 比如矩形波,从0-1时,为上升沿,1-0时,为下降沿。 在你需要某个信号为ON,而又不希望该信号的常ON(或OFF)状态影响你使用时,可用上升沿和下降沿指令。 上升沿就是从0变成1中间的过程。 下降沿就是从1变成0中间的过程

  • Curator典型应用场景之-分布式计数器

    之前我们了解了基于Corator的分布式锁之后,我们就很容易基于其实现一个分布式计数器,顾名思义,计数器是用来计数的,利用ZooKeeper可以实现一个集群共享的计数器。只要使用相同的path就可以得到最新的计数器值,这是由ZooKeeper的一致性保证的。Curator有两种计数器。 SharedCount这个类使用int类型来计数。主要涉及三个类。 SharedCount SharedCountReader SharedCountListener复制 SharedCount代表计数器,可以为它增加一个SharedCountListener,当计数器改变时此Listener可以监听到改变的事件,而SharedCountReader可以读取到最新的值,包括字面值和带版本信息的值VersionedValue。SharedCount必须调用start()方法开启,使用完之后必须调用close关闭它。 SharedCount有以下几个主要方法 /**强制设置值*/ publicvoidsetCount(intnewCount)throwsException; /**第一个参数提供当前的

  • 《茶马古道》观后感——朝圣之路

          这几天吴京的《战狼2》很火,很多人跑去电影院看这部电影,我没时间去看,不知道这部电影到底有什么奇特之处,能创造中国电影票房第一,其实对于我来说不太喜欢扎堆,别人都去看,我就不看。相比而言,近期上映的一部电影,却有点暗淡了,这部电影就是《冈仁波齐》,其实我挺想去看这部电影的,但无奈附近好多电影院没有排期,从小对藏民的耳濡目染,对他们的信仰,思想深深好奇,总想透过它们看到一些东西,但一直却看不透。没有机会看《冈仁波齐》,就看了一部“历史悠久”的纪录片《茶马古道》,在这部片中有一集《朝圣之路》,我觉得和“冈仁波齐”不相上下,看过之后会让你深深的沉思。        很小的时候,有亲戚去过西藏,回来讲过两个故事,使我深深的记在了心在,也由此,一直好奇藏民的信仰。第一件是,在西藏有很多乞丐,他们每天去乞讨,但无论每天要到多少钱,只会留一块钱给自己买一些吃的,其他的全部捐给寺庙,每天如此,每年如此,另一个故事就是有关朝圣的故事,很多藏民家庭全家去朝圣,带着自

  • Golang访问Redis初体验

    go语言的client在redis官网上有很多l客户端,个人感觉redigo使用起来更人性化,重要的是源代码结构很清晰,重要的是支持管道、发布和订阅、连接池等等,所以我选择redigo作为尝试. 1.redigo的安装 终端运行: gogetgithub.com/garyburd/redigo/redis,安装完成后在$GOPATH/src下有相关的文件目录 这是正常的安装方式,不知道什么原因,这块我死活安装不成功. 没办法,从github网上直接下载redigo-master.zip工程包,将redis文件夹直接拷贝到$GOPATH/src/github.com/garyburd/redigo 2.测试redigo 虚拟机启动redis服务,打开LiteIDE,新增一个go文件: //RedisTestprojectmain.go packagemain import( "fmt" "github.com/garyburd/redigo/redis" ) funcmain(){ c,err:=redis.Dial("tcp","192.168.74.128:

  • 如何在异步请求时设置RequestHeader

    一、为何要用到setRequestHeader  通常在HTTP协议里,客户端像服务器取得某个网页的时候,必须发送一个HTTP协议的头文件,告诉服务器客户端要下载什么信息以及相关的参数。而XMLHTTP就是通过HTTP协议取得网站上的文件数据的,所以也要发送HTTP头给服务器。但是XMLHTTP默认的情况下有些参数可能没有说明在HTTP头里,这是当我们需要修改或添加这些参数时就用到了setRequestHeader方法。 二、js设置   varxmlHttp=newXMLHttpRequest();//这里没有做IE5、6兼容   在发送请求之前,调用方法xmlHttp.setRequestHeader('xxxx','yyyy');即可 三、jquery设置   ajax函数中,有一个beforeSend方法,这个方法接受一个参数,就代表了发起异步请求的XMLHttpRequest对象,我们可以用该对象的setRequestHeader方法实现我们的目的:如下示例 $("#test").click(function(){ $.ajax({ type:"GET", url:"xxx

  • 【流水】2022.11.15

    绷不住就写,这是BK的流水写作风格 大家恐怕都知道为什么BK绷不住吧 我已经做好了听一些大家点的歌的准备 毕竟说先放中文嘛。 结果……结果…… 调挺熟,但是只有调熟 就……梦幻馆一路开到了畜生界,您懂吧 想起: 某东方UP主 打虹龙洞 见四面 啊,这!难不成是莲子和梅莉 道中 哇这个道中,越来越扑朔迷离了 到了关底 你jb谁啊? 不过既然都这么离谱了 下回直接放原曲呗? 原曲的旧作式音源也不戳 虽然但是,确实放了两首,这事好的 第二首是什么? 请告诉我。 今天去信息学考 发现这个考试挺随便的 高三的和我相互谦让: “我们是高三来补考的,你先跟着进去啊。” “我是衡实的。” 乐。 监考老师遇见补考的怎么办? “你就跟着进这场就好了。” 我是怎么办的呢? “你是朱文虎的学生吧?来,跟我上楼。” 然后考场里查名单的老师:“(我的真实名字)?” “你就在底下手写个名。写(我的真实名字)就行了。” 题目:A*BProblem。 今天考试 寄了 本来还想拿rank5的 路上和虎哥聊天,节选一部分: 开始: 你CSP都哪里挂了 后来: 你平常还骑自行车啊 接着: 基本上玉米暑假后一个月…

相关推荐

推荐阅读