目录标题
1、Spring概述
一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器(框架)。
1.1 简介
Spring : 春天 —->给软件行业带来了春天
2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架。
2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。
很难想象Rod Johnson的学历 , 他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
Spring理念 : 使现有技术更加实用 . 本身就是一个大杂烩 , 整合现有的框架技术
官网 : http://spring.io/
官方下载地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/
GitHub : https://github.com/spring-projects
1.2 优点
Spring是一个开源免费的框架 , 容器 .
Spring是一个轻量级的框架 , 非侵入式的 .
控制反转 IoC , 面向切面 Aop
对事物的支持 , 对框架的支持
一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器(框架)。
1.3 组成
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
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。
1.4 拓展
spring 弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱!
spring -> spring mvc -> spring boot
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!
Spring Boot与Spring Cloud
Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;
Spring Cloud是基于Spring Boot实现的;
Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;
Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。
SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。
1.5 什么是 Ioc
1. spring前,传统MVC模式
dao文件夹 dao层
package nuc.ss.dao;
//这是一个名为UserDao的接口
// 接口中定义了一个getUser()方法,该方法没有返回值(void)
// 这个接口定义了获取用户数据的抽象行为
public interface UserDao {
void getUser();
}
package nuc.ss.dao;
// UserDaoImpl 是 UserDao接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个打印
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("默认获取用户的数据");
}
}
package nuc.ss.dao;
// UserDaoMysqlImpl 是 UserDao接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个mysql打印
public class UserDaoMysqlImpl implements UserDao {
public void getUser() {
System.out.println("Mysql获取用户数据");
}
}
package nuc.ss.dao;
// UserDaoOracleImpl 是 UserDao接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个Oracle打印
public class UserDaoOracleImpl implements UserDao{
public void getUser() {
System.out.println("Oracle获取用户数据");
}
}
service 文件夹 用户层
package nuc.ss.service;
//这是一个名为UserService的接口
//这个就像是一个约定,说"我要做一个能获取用户信息的功能"。
// 接口中定义了一个getUser()方法,该方法没有返回值(void)
// 这个接口定义了获取用户数据的抽象行为
public interface UserService {
public void getUser();
}
package nuc.ss.service;
import nuc.ss.dao.UserDao;
import nuc.ss.dao.UserDaoImpl;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.dao.UserDaoOracleImpl;
// UserServiceImpl 是 UserService接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个打印
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void getUser() {
userDao.getUser();
}
}
/*
这是自动的向上转型(因为子类对象可以自动转换为父类类型)。
这可以调用父类的所有方法
不能调用子类特有的方法
生活中的例子:
学生都是人,所有学生都可以当做人来看待(向上转型)
但是不是所有的人都是学生(需要向下转型且可能失败)
区别
* UserDaoImpl impl = (UserDaoImpl) userDao; // 这才是强制转换,需要用()
* 不论是接口还是子父类,向上转型可能会丢失子类特有的方法
如果需要使用子类特有的方法,需要向下转型
向下转型前应该用instanceof判断类型,避免出错
*
* */
test文件‘
package nuc.ss.test;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.service.UserService;
import nuc.ss.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//用户实际调用的是业务层,业务层dao层他们不需要调用。业务层调用的才是dao层。用户-->sercive--->dao层。
UserService userService = new UserServiceImpl();
userService.getUser();
}
}
执行结果
默认获取用户的数据
Process finished with exit code 0
如果用户变更为通过mysql进行数据的链接 ,则需要手动改代码。
//用户实际调用的是业务层,业务层dao层他们不需要调用。业务层调用的才是dao层。用户–>sercive—>dao层。
此时只需要变动 sercive 内 UserServiceImpl.java 即可
package nuc.ss.service;
import nuc.ss.dao.UserDao;
import nuc.ss.dao.UserDaoImpl;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.dao.UserDaoOracleImpl;
// UserServiceImpl 是 UserService接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个mysql打印
public class UserServiceImpl implements UserService {
//只变更这一行代码 改变接口的实现即可
private UserDao userDao = new UserDaoOracleImpl();
public void getUser() {
userDao.getUser();
}
}
执行结果:
Mysql获取用户数据
Process finished with exit code 0
同理的,如果用户想从oracl 进行没数据的获取,也是改一行代码
package nuc.ss.service;
import nuc.ss.dao.UserDao;
import nuc.ss.dao.UserDaoImpl;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.dao.UserDaoOracleImpl;
// UserServiceImpl 是 UserService接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个mysql打印
public class UserServiceImpl implements UserService {
//只变更这一行代码 改变接口的实现即可
private UserDao userDao = new UserDaoOracleImpl();
public void getUser() {
userDao.getUser();
}
}
执行结果
Oracle获取用户数据
Process finished with exit code 0
2. 传统MVC模式的缺点
强耦合,服务层的接口实现是写死的,根据用户需求的 变更需要手动变更代码,才能实现默认/,MYSQL/ORACLE等不同方式的数据获取。 因此需要通过一种方式,来降低耦合度,减少源码的修改。
3.spring的解决方式:更改一行代码,Ioc控制反转实现
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
1.更改一处,service层
// 把写死的 private UserDao userDao = new UserDaoOracleImpl();变为通过接口实现
// 利用set进行动态实现值的注入
package nuc.ss.service;
import nuc.ss.dao.UserDao;
import nuc.ss.dao.UserDaoImpl;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.dao.UserDaoOracleImpl;
// UserServiceImpl 是 UserService接口的一个具体实现类
//实现了 接口中的getUser方法
//当前的实现 是进行了一个打印
public class UserServiceImpl implements UserService {
//----------------
// SPRING 改进前的服务层代码
// private UserDao userDao = new UserDaoImpl();// 向上转型
// private UserDao userDao = new UserDaoMysqlImpl();
// private UserDao userDao = new UserDaoOracleImpl();
//----------------
// spring改进后的服务层代码:
// 把写死的 private UserDao userDao = new UserDaoOracleImpl();变为通过接口实现
// 利用set进行动态实现值的注入
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//----------------
public void getUser() {
userDao.getUser();
}
}
用户在使用上,是如何得控制权反转的ioc
import nuc.ss.dao.UserDao;
import nuc.ss.dao.UserDaoImpl;
import nuc.ss.dao.UserDaoMysqlImpl;
import nuc.ss.dao.UserDaoOracleImpl;
import nuc.ss.service.UserService;
import nuc.ss.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//---------------------------
// Spring改进前的用户层代码
//用户实际调用的是业务层,dao层他们不需要调用
//userService UserServiceImpl 向上转型变成了UserService,并实现了接口中的getUser方法,
UserService userService =new UserServiceImpl();
//---------------------------
// Spring改进后的用户层代码 只是新增一条代码
//用户需要什么,就直接get什么
// ((UserServiceImpl)userService).setUserDao(new UserDaoImpl());
// ((UserServiceImpl)userService).setUserDao(new UserDaoMysqlImpl());
((UserServiceImpl)userService).setUserDao(new UserDaoOracleImpl());
/* 注意
UserService userService =new UserServiceImpl();
定义一个userService的时候,userService 从接口的实现类 UserServiceImpl已经向上转型变成了UserService,
并实现了UserService接口中的getUser方法。但向上转型后,就不能访问子类UserServiceImpl自己的特有成员,
也就是我们刚才自己写的setUserDao()方法。
但是此时我们需要的正是把这个Dao的控制权,给到用户,让用户自己拿到setUserDao()方法。
所以必须强转回UserServiceImpl 即:(UserServiceImpl)userService,
这样就成功拿到了 ((UserServiceImpl)userService).setUserDao()方法。
userService通过在用户层的变更,.setUserDao()方法,就可以自由地实现对DAO的控制,进行切换。
切换后,用户需要什么,就直接getUser什么,而不是程序员在后面手动更改业务层的源代码。
这是把主动权交给了客户,让客户去选择自己需要的业务层,而不是像之前的改变Service层中的Dao对象。
也就是,
控制反转了!!!
*/
//---------------------------
userService.getUser();
}
}
private UserDao userDao;
//利用set进行动态实现值的注入!
public void setuserDao(userDao userDao){this.userDao =userDao;
我们使用一个Set接口实现,已经发生了根本性的变化。
之前是程序员自己主动创建实现类(在业务层一个一个创建),现在是被动接收客户需要的实现类(作为参数传递过去)
·之前,程序是主动创建对象!控制权在程序猿手上!
·使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!
这种思想,从本质上解决了问题,程序猿不用再去管理对象的创建了。
系统的耦合性大大降低,可以更加专注地在业务的实现。
4.Ioc控制反转,和spring的关系
Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器(框架)。
1.6 IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。