简介
- Spring框架是由于软件的开发的复杂而创建的,目的就是解决软件开发的复杂性问题,他是基于在JavaBean的基础上来完成之前只能由EJB完成的事情,替代了JDBC的框架(MyBits);给软件行业带来了春天;
- Spring框架使用与任何的Java应用,是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架;
- Spring使得Java EE的开发更加的容易了,他与Struts,Hibernate等单层框架不同,他是致力于提供一个以统一的,高效的方式构造整个应用,并且可以将单层框架以最佳的方式组合在一起,建立一个连贯的体系;可以为POJO(Plain Ordinary Java Object)对象提供企业级的服务。
- Spring是在2002年,来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,2003年,Spring框架以interface21框架为基础,重新设计.发布了1.0正式版;
Spring官网: https://spring.io/
Spring的下载: https://spring.io/projects/spring-framework#learn
版本介绍:
我们在下载软件会遇到诸如release,stable,alpha,beta,pre,current,eval,rc,snapshot等版本,程序猿下载插件时尤为常见,介绍几个版本:
- snapshot(快照),也即开发版,我们创建maven项目时,编辑器会自动给我们填入 1.0-SNAPSHOT版本,也就是1.0开发版,这个版本不能使用,因为该版本处于开发的过程,所以运行时会不时地更新,导致功能变化,正式环境中不得使用snapshot版本的库;
- alpha,内部测试版,来源于字母α,是比较早的版本,主要是给开发人员和测试人员测试和找BUG用的,不建议使用;
- beta,公开测试版,来源于字母β,这是比alpha进一步的版本,面向公众测试,但是不建议使用
- pre,这个和alpha版本类似,有时还会细分为M1,M2版本,不建议使用;
- RC(Release Candidate) 顾名思义么 ! 用在软件上就是候选版本。系统平台上就是发行候选版本;
- GA(General Availability)正式发布的版本,在国外都是用GA来说明release版本的;
- release,发行版,这是release的中文意思,也就是官方推荐使用的版本;
- stable,稳定版,这个版本相比于测试版更加稳定,去除了测试版许多的bug,完善了一些功能,建议使用;
- current,最新版,但是不一定是稳定版本,需要看一下是否还有release或者stable等版本;
- eval,评估版。可能会有一个月或者固定时间的使用期限;
SpringGithub地址:https://github.com/spring-projects/spring-framework
Spring官网下载地址:https://repo.spring.io/release/org/springframework/spring/
Spring的优点:
- Spring是一个轻量级的框架,非入侵式框架;(使用时没有其他的依赖,也不需要导入其他的包);
- 控制反转(IOC)和面向切面(AOP)的容器框架;
- Spring对事务的支持;
- Spring对框架的支持,不需要任何成本就可以引入其他的框架
Spring的框架
Spring的架构:MVC架构
Spring框架是一个分层的架构,由7个定义良好的模块组成.Spring模块构建在核心容器上,核心容器定义了创建、配置和管理bean的方式;
从下向上看spring的主要内容:
Test:Spring支持Junit单元测试
核心容器(IOC):Bean(Bean工厂,创建对象)、Core(一切的基础)、Context(上下文)、SpEL(Spring的表达式语言);
AOP:AOP、Aspects
对数据访问的支持:JDBC、ORM、Transaction、JMS(java邮件服务)
对web的支持:Spring MVC
组成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)、独立应用程序、测试环境之间重用。
Spring组件:
SpringBoot和Spring Cloud
SpringBoot:一款可以快速构建Spring应用的脚手架;约定大于配置,承上启下;
- Spring Boot是构建所有基于Spring的应用程序的起点。
- Spring Boot旨在尽可能快地启动和运行,只需最少的Spring前端配置。
Spring Cloud:基于SpringBoot实现的;他是一个生态圈;通过实施经过验证的模式,为微服务带来弹性,可靠性和协调,从而简化了分布式微服务式架构。
IOC
IOC----inversion of control控制反转
- 控制反转模式(也称作依赖性介入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器 (在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。
- 在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。下表列出了 IOC 的一个实现模式。
IOC的别名:依赖注入(DI)
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦(微服务)。
引入一个图来方便理解:
IOC让程序的耦合性大大降低,方便了模块的独立;(低耦合高内聚)
实例:
HelloSpring
- 1.导入jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
- 创建实体类
package com.zhang.pojo;
public class HelloSpring {
private String name;
public HelloSpring() {
}
public HelloSpring(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+name);
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
- 创建Spring的配置文件 bean.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean 就是一个java对象,有spring创建和管理-->
<bean class="com.zhang.pojo.HelloSpring">
<property name="name" value="Spring"/>
</bean>
</beans>
- 编写测试类;
package SpringTest;
import com.zhang.pojo.HelloSpring;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
@Test
public void tast(){
//解析bean.xml配置文件,生产管理相同的bean对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//通过bean得到这个对象的实体
HelloSpring hello = (HelloSpring) context.getBean("hello");
hello.show();
}
}
以上代码编译运行的结果如下图所示:
通过这个测试我们可以看出在这个测试中,
- Hello对象就是由Spring创建的,而Hello对象的属性的值是由Spring容器创建的;
- bean.xml 配置文件是用来管理Java对象;
- 而Spring就像一个容器一样,存放了许多的对象;
但是如何将bean.xml文件转换成为对象的,其实主要就是经过了以下两步:
- 解析配置文件,
- 通过反射创建对象并且设置值;
控制反转
控制:谁来控制对象的创建,传统应用程序是由程序本身控制创建的,但是在使用Spring之后,对象就由Spring创建;
反转:程序本身不创建对象,变成了被动的接收对象;
依赖注入:就是利用set的方法进行的注入;IOC就是一种编程思想,有一种主动的编程变成了被动的接收;
所谓的IOC就是:由Spring创建,管理,和装配对象;
IOC创建对象的方式
我们平时创建对象的方式就是:有参构造,无参构造;
但是在Spring中又是如何实现的呢?
- 创建实体类
package com.zhang.pojo;
public class User {
private String name;
private String sex;
private int age;
public User() {
System.out.println("User的无参构造");
}
public User(String name) {
System.out.println("User的有参构造");
this.name = name;
}
public User(String name, int age) {
System.out.println("User的有参构造2");
this.name = name;
this.age = age;
}
public User(String name, String sex, int age) {
System.out.println("User的有参构造3");
this.name = name;
this.sex = sex;
this.age = age;
}
public void setName(String name) {
System.out.println(name+":"+System.currentTimeMillis());
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 编写配置文件。beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Spring 的配置文件-->
<!--bean 代表一个对象-->
<!--alias 别名-->
<bean class="com.zhang.pojo.User">
<property name="name" value="user"/>
</bean>
<!--使用构造器的参数下标进行赋值-->
<bean class="com.zhang.pojo.User">
<constructor-arg index="0" value="zhang"/>
<constructor-arg index="1" value="18"/>
</bean>
<!--使用名字进行赋值-->
<bean class="com.zhang.pojo.User">
<constructor-arg name="name" value="zhang3"/>
<constructor-arg name="age" value="8"/>
</bean>
<!--使用类型进行赋值-->
<bean class="com.zhang.pojo.User">
<constructor-arg type="java.lang.String" value="zhang4"/>
<!--<constructor-arg type="java.lang.Integer" value="16"/>-->
<!--<constructor-arg type="java.lang.String" value="男"/>-->
</bean>
</beans>
- 测试类
package com.zhang;
import com.zhang.pojo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserTest {
@Test
public void test(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.toString();
}
@Test
public void test2(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user4");
System.out.println(user);
}
}
以上代码编译运行的结果如下:
使用构造器参数设置下标进行赋值
使用名字进行赋值
使用类型进行赋值
从上面的运行结果来看,当用类型进行赋值是,方法必须要保持一致,否则就会报错;所以一般不推荐使用,使用最多的是通过参数名进行赋值;
IOC创建对象时必须要有一个无参构造方法;