spring初识
framework
框架就是某些个人或者组织定义了一系列的类或者接口,提前定义好了一些实现,用户可以在这些类和接口的基础之上,使用这些类来迅速的形成某个领域或者某个行业的解决方案,简化开发的过程,提高开发的效率。就好比:你要盖一座房子,先把柱子,房梁等先建设好,然后只需要向房子中填充就可以了,可以按照自己的需求进行设计,其实我们做的项目、系统都是类似的方式,如果所有的代码全部都需要自己实现,那么这个工程就太庞大了,所以可以先创建出一些基础的模板框架,开发人员只需要按照自己的需求向架子中填充内容,完成自己独特需求即可,这就是框架存在的意义。其实我们之前定义的简单的工具类这些东西也是类似的原理,只不过比较单一简单而已,因此,在现在的很多项目系统开发的过程中都是利用框架进行开发。
架构的发展历程
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
java主流架构演变之路
1、Servlet+jsp+JavaBean
首先客户端想Servlet发送doGet/doPost请求,Servlet收到请求之后调用JavaBean,javaBean通过与数据交互,获得数据返回到ServLet中,Servlet获得数据,返回到Jsp,然后响应到浏览器,获得最终数据。
优点:编写代码简单,适合微小型项目,快速编码发布
缺点:代码高聚合,不适合扩展
2、MVC三层架构
MVC三次架构从Servlet+jsp+JavaBean演变而来,为了解决刚刚提到的高聚合不适合扩展的弊端,将代码进行拆分,分为web层、service层,以及dao层,这样代码在后面扩展的时候就比较容易了。
3、使用EJB进行应用的开发,但是EJB是重量级框架(在使用的时候,过多的接口和依赖,侵入性强),在使用上比较麻烦
4、Struts1/Struts2+Hibernate+Spring
5、SpringMVC+Mybatis+Spring
6、SpringBoot开发,约定大于配置
spring
spring5中文手册:github.com/DocsHome/sp…
压缩包下载地址:repo.spring.io/list/libs-s…
简介
Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。
Spring最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。 Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming,AOP)
核心
spring是一个轻量级的开源框架。
spring为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题
spring是一个IOC和AOP的容器框架。
IOC:控制反转
AOP:面向切面编程
容器:包含并管理应用对象的生命周期
使用spring的优点
1、Spring通过DI、AOP和消除样板式代码来简化企业级Java开发
2、Spring框架之外还存在一个构建在核心框架之上的庞大生态圈,它 将Spring扩展到不同的领域,如Web服务、REST、移动开发以及NoSQL
3、低侵入式设计,代码的污染极低
4、独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
5、Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦
6、Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供了更好的复用
7、Spring的ORM和DAO提供了与第三方持久层框架的的良好整合,并简化了底层的数据库访问
8、Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
9、任何一个语言或者任何一个框架想要立于不败之地,那么很重要的就是它的生态。
spring的模块划分图
模块解释 Test:Spring的单元测试模块
Core Container:核心容器模块
AOP+Aspects:面向切面编程模块
Instrumentation:提供了class instrumentation支持和类加载器的实现来在特定的应用服务器上使用,几乎不用
Messaging:包括一系列的用来映射消息到方法的注解,几乎不用
Data Access/Integration:数据的获取/整合模块,包括了JDBC,ORM,OXM,JMS和事务模块
Web:提供面向web整合特性
IOC(Inversion of Control):控制反转
IOC是一种设计思想,在Java开发中,将你设计好的对象交给容器控制,而不是显示地用代码进行对象的创建。
把创建和查找依赖对象的控制权交给 IoC 容器,由 IoC 容器进行注入、组合对象之间的关系。这样对象与对象之间是松耦合、功能可复用(减少对象的创建和内存消耗),使得程序的整个体系结构可维护性、灵活性、扩展性变高。 所谓IOC ,就简短一句话:对象由spring来创建、管理,装配!
为什么使用IOC: 拿我们用的电脑来说,模块基本都是相互独立的,比如我们的鼠标键盘都是通过一个接口直接插在主板上面的,如果把鼠标和键盘直接焊死在主板上,那如果键盘或者鼠标坏了,那岂不是还得重新焊一个上去才行,这样的方式,扩展性多差!所以我们的IOS就是类似的概念,设计一个接口,让模块可以自由的插拔。
1、接口分离原则ISP(the Interface Segregation PrincipleISP)
模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来不要将鼠标(具体实现)直接焊在主板上,使用插口(抽象)连接; 现在接口有了,但是无法热插拔。 每次鼠标坏了需要关掉电脑才能更换(实现类换了还是需要去变更代码)
IUserDao dao=new UserDaoImpl();
2. 依赖倒置原则DIP(the Dependency InversionPrinciple DIP)
具体实现依赖抽象,下层依赖上层。 分离依赖倒置原则使鼠标、键盘和电脑成为独立的的互不相干的对象,当电脑(上层)没有鼠标可以正常启动但是鼠标(下层)没有电脑则一无是处 ,控制权就被反转了(IOC)。 所以鼠标需要依赖USB(DI)才能使用。
之前——正转: 主板焊接>鼠标 电脑没有鼠标则无法启动
现在——反转: 电脑<依赖鼠标 引入DI可以实现IOC
IOC是DIP的设计原理,DI是IOC的具体实现
鼠标坏了很快就可以换一个,虽然会涉及短暂无法使用, 但是产生的变更极少。
IUserDao dao=从ioc种获取 涉及到的代码变更极少。
IOC代码实现
一般实现有三种方式,分别是:
1、手动导入spring相关jar包
2、使用maven+注解xml的方式
3、使用springboot+javaconfig的方式。
下面主要介绍第二种方式,第一种基本也不用了,第三种到springboot再进行介绍。
1、使用IDE创建一个project
2、选择创建maven项目
3、配置项目名称相关信息
其中Name为项目名称、Location为我们项目要保存的路径,GroupId一般为公司的域名倒置,ArtifactId为项目名称即可,Version默认即可。
创建完成后如下(pom.xml为刚刚我们配置的内容):
4、使用maven仓库导入spring包
注意:spirng5.x以上版本,必须使用jdk1.8+ ,并且已经提供jdk1.9的实现
1、打开maven仓库地址mvnrepository.com/
2、搜索spring
第一个为springIOC的入口,我们点进去,并选择一个稳定版
选择maven导入,拷贝maven代码
3、将拷贝的maven代码粘贴到pom.xml中
初始化创建的pom.xml文件,需要自己添加
<dependencies></dependencies>
4、修改idea的maven配置信息
maven配置信息修改为自己安装的maven信息,如下
5、maven根据依赖自动下载相关jar包
可以看到maven已经帮我们下载好spring相关的jar包了
注:虽然我们只下载spring-context,但是maven会自动根据相关依赖,同步下载相关的jar包。
5、创建spring-ioc.xml
填写文件名,最终如下:
6、创建User bean
package com.jony.beans;
public class User {
private Integer id;
private String userName;
private String realName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + ''' +
", realName='" + realName + ''' +
'}';
}
public User() {
System.out.println("User bean 已经加载了");
}
public User(Integer id, String userName, String realName) {
this.id = id;
this.userName = userName;
this.realName = realName;
}
}
7、创建test类
@Test需要使用junit测试,只需要在maven的pom.xml添加依赖即可
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
最终,我们可以看依稀maven引入jar包的视图
通过以上操作,我们可以看到如下,spring相关的jar包依赖关系。就如前面提到,maven的好处就是会把相关依赖的jar包都导入进来
同时可以看到 junit下面有个scope(作用域),scope一共有以下几个值:
1、compile:默认的scope,运行期有效,需要打入包中
2、provided:编译期有效,运行期不需要提供,不会打入包中
3、runtime:编译不需要,在运行期有效,需要导入包中。(接口与实现分离)
4、test:测试需要,不会打入包中
5、system:非本地仓库引入、存在系统的某个路径下的jar。(一般不使用)
8、在spring-ioc中添加User bean
<?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 class="com.jony.beans.User" id="user"></bean>
</beans>
9、测试
package com.jont.ioc;
import com.jony.beans.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class IocTest {
@Test
public void test01(){
// 加载spring容器
//ApplicationContext spring的顶层核心接口
// ClassPathXmlApplicationContext 根据项目路径的xml配置来实例化spring容器
// FileSystemXmlApplicationContext 根据磁盘路径的xml配置来实例化spring容器
// AnnotationConfigApplicationContext 根据javaconfig 来配置实例化spring容器
// 在容器实例化的时候 就会加载所有的bean
ApplicationContext ioc=new ClassPathXmlApplicationContext("spring-ioc.xml");
//通过发射机制拿到User bean
User bean = ioc.getBean(User.class);
System.out.println(bean);
}
}
执行结果
总结
DI与IOC
很多人把IOC和DI说成一个东西,笼统来说的话是没有问题的,但是本质上还是有所区别的,希望大家能够严谨一点,IOC和DI是从不同的角度描述的同一件事,IOC是从容器的角度描述,而DI是从应用程序的角度来描述,也可以这样说,IOC是依赖倒置原则的设计思想,而DI是具体的实现方式
在面向对象设计的软件系统中,底层的实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。
ioc优点
解耦
-
集中管理
-
功能可复用(减少对象的创建和内存消耗)
-
使得程序的整个体系结构可维护性、灵活性、扩展性变高
-
解耦