Spring学习总结(1)- IOC
一、Spring框架概述
Spring是一个开源免费的框架,为了解决企业应用开发的复杂性而创建。Spring框架是一个轻量级的解决方案,可以一站式地构建企业级应用。Spring是模块化的,所以可以只使用其中需要的部分。可以在任何web框架上使用控制反转(IoC),也可以只使用Hibernate集成代码或JDBC抽象层。它支持声明式事务管理、通过RMI或web服务实现远程访问,并可以使用多种方式持久化数据。它提供了功能全面的MVC框架,可以透明地集成AOP到软件中。
Spring被设计为非侵入式的,这意味着你的域逻辑代码通常不会依赖于框架本身。在集成层(比如数据访问层),会存在一些依赖同时依赖于数据访问技术和Spring,但是这些依赖可以很容易地从代码库中分离出来。
Spring框架是基于Java平台的,它为开发Java应用提供了全方位的基础设施支持,并且它很好地处理了这些基础设施,所以你只需要关注你的应用本身即可。
Spring可以使用POJO(普通的Java对象,plain old java objects)创建应用,并且可以将企业服务非侵入式地应用到POJO。这项功能适用于Java SE编程模型以及全部或部分的Java EE。
那么,做为开发者可以从Spring获得哪些好处呢?
1,不用关心事务API就可以执行数据库事务;
2,不用关心远程API就可以使用远程操作;
3,不用关心JMX API就可以进行管理操作;
4,不用关心JMS API就可以进行消息处理。
①JMX:Java Management eXtension,Java管理扩展,是一个为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
②JMS:Java Message Service,Java消息服务,是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。
1,Spring框架特征与功能
轻量 |
从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。 |
控制反转Ioc |
Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。 |
面向切面Aop |
Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。 |
容器 |
Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。 |
框架 |
Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。 |
MVC |
Spring的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架,Spring MVC是一个非常受欢迎的轻量级Web框架。 |
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
2,Spring组成
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式。Spring结构如下:
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
核心容器 |
核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 |
Spring 上下文 |
Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 |
Spring AOP |
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。 |
Spring DAO |
JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 |
Spring ORM |
Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 |
Spring Web 模块 |
Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 |
Spring MVC 框架 |
MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。 |
Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。
二,Eclipse中创建Maven Web项目
创建Maven Project
创建一个简单的项目,不使用模板
"Group Id"中输入项目的基本包名,在"Artifact Id"中输入项目名,"Packaging"选择war打包方式
刚创建出来的Maven项目报错,说找不到Web.xml文件:
鼠标右键项目-->Properties-->Project Facets如下所示:
选择java版本为1.8(我系统中的JDK版本是1.8的),并去掉Dynamic Web Module,点击Apple应用,如下图:
重新勾选上Dynamic Web Module,并选择Version,如下所示:
点击Further configuration available...,创建webRoot目录,点击ok,如下所示:
点击Apply,点击ok
这样就不会再报找不到Web.xml的错误了。
完整的项目结果如下:
三,IoC
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
四,使用XML方式实现IOC(控制反转)
pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>Zender</groupId><artifactId>SpringDemo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.3.0.RELEASE</spring.version></properties><dependencies><!-- Spring Core --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><!-- Spring Context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency></dependencies> </project>
1,创建对象
创建2个实体类:Person,ExtendedAttribute
Person:
public class Person {private String name;private int age;private ExtendedAttribute exAttribute;public Person(String name, int age, ExtendedAttribute exAttribute) {this.name = name;this.age = age;this.exAttribute = exAttribute;}public Person(String name, int age) {this.name = name;this.age = age;}public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public ExtendedAttribute getExAttribute() {return exAttribute;}public void setExAttribute(ExtendedAttribute exAttribute) {this.exAttribute = exAttribute;}public String toStringNameAge() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", sex=" + exAttribute.getSex() + ", addrs=" + exAttribute.getAddrs() + "]";} }
ExtendedAttribute:
//Person的扩展属性类 public class ExtendedAttribute {private String sex;private String addrs;public ExtendedAttribute(String sex, String addrs) {this.sex = sex;this.addrs = addrs;}public ExtendedAttribute() {}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddrs() {return addrs;}public void setAddrs(String addrs) {this.addrs = addrs;} }
IOCBeans.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 1,无参构造方法创建对象 --><bean id="person" class="com.zender.bean.Person"></bean><!--,2,有参构造方法创建对象 --><bean id="person2" class="com.zender.bean.Person"><constructor-arg name="name" value="Zender"/><constructor-arg name="age" value="21"/></bean><!-- 也可是使用索引来确定参数 --><!-- <bean id="person2" class="com.zender.bean.Person"><constructor-arg name="0" value="Zender"/><constructor-arg name="1" value="21"/></bean>--><!-- 3,有参构造方法创建对象 --><bean name="personExtendedAttribute" class="com.zender.bean.ExtendedAttribute"><constructor-arg name="sex" value="男"/><constructor-arg name="addrs" value="重庆"/></bean><bean id="person3" class="com.zender.bean.Person"><constructor-arg name="name" value="Zender"/><constructor-arg name="age" value="21"/><constructor-arg name="exAttribute" ref="personExtendedAttribute"/></bean> </beans>
测试类:
public class PersonTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("IOCBeans.xml");//使用无参构造创建对象Person p = (Person) context.getBean("person");System.out.println(p.toStringNameAge());//使用有参构造创建对象p = (Person) context.getBean("person2");System.out.println(p.toStringNameAge());//使用有参构造属性赋值p = (Person) context.getBean("person3");System.out.println(p.toString());} }
运行结果:
2,对象的作用域
从IOC容器中取回的对象默认是单例的:
public class PersonTest2 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("IOCBeans.xml");Person p = (Person) context.getBean("person");Person p2 = (Person) context.getBean("person");System.out.println(p == p2);} }
运行结果:
我们可以使用scope属性指定作用域,作用域有一下7个:
修改id为person的bean:
<bean id="person" class="com.zender.bean.Person" scope="prototype"></bean>
运行结果:
3,延迟初始化bean
ApplicationContext实现的默认行为就是再启动时将所有 singleton bean提前进行实例化。 通常这样的提前实例化方式是好事,因为配置中或者运行环境的错误就会被立刻发现,否则可能要花几个小时甚至几天。如果你不想 这样,你可以将单例bean定义为延迟加载防止它提前实例化。延迟初始化bean会告诉Ioc容器在第一次需要的时候才实例化而不是在容器启动时就实例化。
在XML配置文件中,延迟初始化通过<bean/>元素的lazy-init属性进行控制,比如:
<bean id="person" class="com.zender.bean.Person" lazy-init="true"></bean>
4,初始化bean,执行回调函数方法
在XML配置文件中,回调函数方法通过init-method属性和destroy-method属性进行控制,比如:
person:
public class Person {private String name;private int age;private ExtendedAttribute exAttribute;public Person(String name, int age, ExtendedAttribute exAttribute) {this.name = name;this.age = age;this.exAttribute = exAttribute;}public Person(String name, int age) {this.name = name;this.age = age;}public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public ExtendedAttribute getExAttribute() {return exAttribute;}public void setExAttribute(ExtendedAttribute exAttribute) {this.exAttribute = exAttribute;}public void init(){System.out.println("调用person的init方法!");}public void destroy(){System.out.println("调用person的destroy方法!");} }
修改id为person的bean:
<bean id="person" class="com.zender.bean.Person" init-method="init" destroy-method="destroy"></bean>
测试代码:
public class PersonTest2 {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("IOCBeans.xml");Person p = (Person) context.getBean("person");} }
运行结果:
五,使用注解方式实现IOC(控制反转)
在使用传统的xml配置完成IOC的,如果内容比较多则配置需花费很多时间,通过注解可以减轻工作量,但注解后修改要麻烦一些,偶合度会增加,应该根据需要选择合适的方法。例如:
项目结果整体如下:
User实体类:
public class User {private String name;private String pwd;public User(String name, String pwd) {this.name = name;this.pwd = pwd;}public User() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "User [name=" + name + ", pwd=" + pwd + "]";} }
iUserDao接口:
public interface iUserDao {public String addUser(User u); }
UserDao类:
@Component public class UserDao implements iUserDao {@Overridepublic String addUser(User u) {return "添加用户" + u.getName() + "成功!";} }
注意:
在类上增加了一个注解Component,在类的开头使用了@Component注解,它可以被Spring容器识别,启动Spring后,会自动把它转成容器管理的Bean。使用Compont注解时不指定名称时,Spring会使用默认的命名机制,即简单类名且第一个字母小写。
除了@Component外,Spring提供了3个功能基本和@Component等效的注解,分别对应于用于对DAO,Service,和Controller进行注解:
1,@Repository 用于对DAO实现类进行注解。
2,@Service 用于对业务层注解,但是目前该功能与 @Component 相同。
3,@Constroller用于对控制层注解,但是目前该功能与 @Component 相同。
UserService类:
@Component public class UserService {@Autowiredprivate iUserDao userDao;public void UserServiceAddUser(User u){String text = userDao.addUser(u);System.out.println(text);} }
注意:
这里使用了自动装配,在iUserDao成员变量上增加了一个注解@Autowired,该注解的作用是:
可以对成员变量、方法和构造函数进行注解,来完成自动装配的工作,通俗来说就是会根据类型从容器中自动查到到一个Bean给iUserDao成员变量。
装配注解主要有:@Autowired、@Qualifier、@Resource,它们的特点是:
1、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入,@Resource注解是由J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;如果Maven项目是1.5的JRE则需换成更高版本的。例如:
@Resource(name="iUserDao2") private iUserDao userDao;
2、@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用,例如:
@Autowired private iUserDao userDao;
3、@Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上。
4、@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。
5、@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。例如:
@Autowired @Qualifier("iUserDao2") private iUserDao userDao;
6、@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要。
@Autowired(required=true) @Qualifier("iUserDao2") private iUserDao userDao;
7、@Resource装配顺序
1,如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
2,如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
3,如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
4,如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
IOCBeans.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.zender"></context:component-scan> </beans>
注意:
粗斜体字是新增的xml命名空间与模式约束文件位置。增加了注解扫描的范围,指定了一个包,可以通过属性设置更加精确的范围如:
<context>标记常用属性配置:
resource-pattern:对指定的基包下面的子包进行选取。
<context>子标记:
include-filter:指定需要包含的包。
exclude-filter:指定需要排除的包。
例如:
<!-- aspectj类型,扫描com.zender.dao下所有的类,排除entity下所有的类 --><context:component-scan base-package="com.zender" ><context:include-filter type="aspectj" expression="com.zender.dao. *" /><context:exclude-filter type="aspectj" expression="com.zender.entity.*.*" /></context:component-scan>
1,resource-pattern:仅希望扫描特定的类而非基包下的所有类。
2,include-filter:需要包含的目标类型。
3,exclude-filter:需要排除的目标类型。
4,type表示采的过滤类型,共有如下5种类型:
过滤类型 |
例如 |
解释 |
annotation |
org.example.SomeAnnotation |
注解了SomeAnnotation类型的类 |
assignable |
org.example.SomeClass |
所有扩展或者实现SomeClass的类 |
aspectj |
org.example..*Service+ |
AspectJ语法表示org.example包下所有包含Service的类及其子类 |
regex |
org\.example\.Default.* |
Regelar Expression,正则表达式 |
custom |
org.example.MyTypeFilter |
通过代码过滤,实现org.springframework.core.type.TypeFilter接口 |
例如:
<!-- 扫描注解了org.springframework.stereotype.Repository的类 --><context:component-scan base-package="com.zender"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" /></context:component-scan>
测试类:
public class IOCTest {public static void main(String[] args) {ApplicationContext context=new ClassPathXmlApplicationContext("IOCBeans.xml");UserService us = context.getBean("userService", UserService.class);us.UserServiceAddUser(new User("Zender","123"));} }
运行结果:
转载于:https://www.cnblogs.com/Zender/p/7856350.html
Spring学习总结(1)- IOC相关推荐
- Spring学习-理解IOC和依赖注入
最近刚买了一本介绍ssm框架的书,里面主要对Mybatis.spring.springmvc和redis做了很多的讲解,个人觉得虽然有的内容我看不懂,但是整体上还是不错的.最近正在学习中,一边学习一边 ...
- Spring学习篇:IoC知识整理(一)
现在正通过spring的官方文档学习spring,将自己学习时的点点滴滴记录下来. Ioc知识整理(一): IoC (Inversion of Control) 控制反转. 1.bean的别名 我们每 ...
- Spring学习3之IOC创建对象的方式
前言 我们学习了IOC是什么,并且练习了一个Spring程序,知道了对象是由Spring创建,管理,装配.IOC有哪些创建对象的方法呢? 一.IOC创建对象的方式 <!--IOC创建对象的方式 ...
- Spring学习1之ioc
前言 什么是Spring: Spring是一个开源的免费的框架(容器)! Spring是一个轻量级的.非入侵式的框架! 控制反转(IOC) ,面向切面编程(AOP)! 支持事务的处理,对框架整合的支持 ...
- Spring学习笔记(三) AOP_annotation,AOP_XML
在学习课程以前,听说AOP有种很神秘的感觉,好像很好深的技术.其实原理很简单,使用动态代理的方式给程序增加逻辑.与此相似的有struts2中的filter拦截器. 再讲AOP之前先把需求说一下: 同S ...
- 第四阶段--Spring学习-02
第四阶段--Spring学习 7.IOC/DI配置管理第三方bean 7.1 环境准备 7.2 对数据源进行配置管理思路: 7.3 实现Druid管理 步骤1:导入`druid`的依赖坐标 步骤2:配 ...
- Spring学习(四)IOC详解
本文借鉴:Spring学习(特此感谢!) 一.简介 概念:控制反转是一种通过描述(在 Java 中可以是 XML 或者注解)并通过第三方(Spring)去产生或获取特定对象的方式.(被动创建) 优势: ...
- Spring学习(二)Spring IoC 和 DI 简介
本文借鉴:Spring学习(特此感谢!) 一.IOC(控制反转) 定义:反转控制 (Inversion Of Control)的缩写,即创建对象的反转控制. 正向控制:若要使用某个对象,需要自己去负责 ...
- 【Spring学习】IOC容器
1.IOC的理论背景 我们知道在面向对象设计的软件系统中,它的底层都是由N个对象构成的,各个对象之间通过相互合作,最终实现系统地业务逻辑. 图1 软件系统中耦合的对象 如果我们打开机械式手表的后盖,就 ...
- Spring学习笔记(一):初识IOC和DI
学习资料来源:http://how2j.cn/k/spring/spring-ioc-di/87.html 首先,不必为看到两个新名词而感到头疼,理解了它们的作用就会发现其实是很简单的东西 Sprin ...
最新文章
- MYSQL注入天书之服务器(两层)架构
- 寿光农商行计算机机房,寿光农商银行 举办2021年新员工入职仪式
- 设计模式-结构型-桥接
- 6-1 数组元素的区间删除
- 医学图像数据集和处理工具【总结】
- 使用.NET Core 3进行Linux编程:第3章
- hexo html代码高亮,使用 prismjs 自定义 Hexo 代码高亮
- 2013蓝桥杯C++B:第39阶台阶(递归法);前缀判断
- 最简单播放m3u8链接的方法
- 用于重尾PLDA的快变分贝叶斯应用于i-vector和x-vector
- Flex 加载Base64编码的二进制字符串图片
- 这一年在非洲(4年一轮回总结完结)
- 滴滴资深分析专家:数据如何驱动业务增长
- 零基础使用Xmind
- 投屏电脑怎么操作?投屏电脑最常用的4种方式
- python随机生成生日测试生日悖论
- linux 安装Mysql步骤
- 深入理解搜索引擎-搜索召回
- linux 查看主板sn_Linux系统查看硬件信息
- 使用XINCheck SDK开发查重系统
热门文章
- c如何接收java指令_java指令和javac指令总结
- 我的世界药水合成表图Java_我的世界药水合成表图高清配方-我的世界药水合成表图一览...
- vue 切换页面没有改变滚动条_VUE建立照片轮播功能
- 深度学习之 epoch batch iteration
- Golang实践录:oracle数据库实践
- Linux无网络升级gcc,Linux离线(手动)升级GCC
- 【java】为什么 HashMap 的加载因子是0.75?
- 【java】java 并发编程 LinkedBlockingDeque
- requirement failed: Can only call getServletHandlers on a running MetricsSystem
- Maven : error: missing or invalid dependency detected while loading class file 'RDD.class'