- Spring:春天 ------->给软件行业带来了春天
- 2002,首次推出了Spring框架的雏形:interface21框架
- Spring框架即是以interface21框架为基础经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版
- Rod Johnson ,Spring framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
- Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!
- SSH :Struct2 + Spring + Hibernate
- SSM:SpringMVC + SPring +Mybatis(现在学的)
- 官网:https://spring.io/
- 官方下载地址:http://repo.spring.io/release/org/springframework/spring
- GitHub:https://github.com/spring-projects/spring-framework
- Spring核心技术地址:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-annotation-config
- mvn-spring依赖地址:https://mvnrepository.com/artifact/org.springframework/spring-webmvc
org.springframework spring-webmvc 5.3.12
- mvn-spring-jdbc依赖地址:https://mvnrepository.com/artifact/org.springframework/spring-jdbc
2. 优点org.springframework spring-jdbc 5.3.12
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的,非入侵式的框架
- 控制反转(IOC),面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持!
3. 组成总结: Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
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。
4. 扩展在spring的官网有这个介绍:现代化的Java开发,说白就是基于Spring的开发
Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发的单个微服务
- 预定大于配置!
Spring Cloud
- Spring Cloud 是基于SpringBoot实现的。
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMvc!承上启下的作用!
弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱!”
创建一个spring-study空项目,删除src
spring-study父类的pom.xml 里面导入spring-webmvc依赖
2. 创建空模块4.0.0 com.xxx spring-study 1.0-SNAPSHOT 17 17 org.springframework spring-webmvc 5.3.12
创建空模块spring-01-ioc1
地址:src/main/java/com/xxx/dao/UserDao.java
代码:
package com.xxx.dao;
public interface UserDao {
void getUser();
}
2.UserDao的实现类
地址:src/main/java/com/xxx/dao/UserDaoImpl.java
代码:
package com.xxx.dao;
public class UserDaoImpl implements UserDao{
public void getUser(){
System.out.println("获取用户的数据");
}
}
3.UserService接口
地址:src/main/java/com/xxx/service/UserService.java
代码:
package com.xxx.service;
public interface UserService {
void getUser();
}
4.UserService实现类
地址:src/main/java/com/xxx/service/UserServiceImpl.java
代码:
package com.xxx.service;
import com.xxx.dao.UserDao;
import com.xxx.dao.UserDaoImpl;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void getUser() {
userDao.getUser();
}
}
5. 测试
import com.xxx.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
//用户实际调用的是业务层,dao层他们不需要接触
UserServiceImpl service = new UserServiceImpl();
service.getUser();
}
}
结果:
获取用户的数据 进程已结束,退出代码为 0
-
这是我们原来的方式 , 开始大家也都是这么去写的对吧 . 那我们现在修改一下 .
-
把Userdao的实现类增加一个 .
地址:src/main/java/com/xxx/dao/UserDaoMysqlImpl.java
代码:
package com.xxx.dao;
public class UserDaoMysqlImpl implements UserDao{
public void getUser(){
System.out.println("获取mysql的数据");
}
}
- 紧接着我们要去使用MySql的话 , 我们就需要去service实现类里面修改对应的实现
- 修改地址:src/main/java/com/xxx/service/UserServiceImpl.java
package com.xxx.service;
import com.xxx.dao.UserDao;
import com.xxx.dao.UserDaoImpl;
import com.xxx.dao.UserDaoMysqlImpl;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoMysqlImpl();
public void getUser() {
userDao.getUser();
}
}
-
测试及结果
-
以此类推,假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .
-
那我们如何去解决呢 ?
-
我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .
地址:src/main/java/com/xxx/service/UserServiceImpl.java
代码:
package com.xxx.service;
import com.xxx.dao.UserDao;
import com.xxx.dao.UserDaoImpl;
import com.xxx.dao.UserDaoMysqlImpl;
public class UserServiceImpl implements UserService {
//private UserDao userDao = new UserDaoMysqlImpl();
private UserDao userDao;
//利用set进行动态实现值得注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
2. 测试
代码:
import com.xxx.dao.UserDaoImpl;
import com.xxx.dao.UserDaoMysqlImpl;
import com.xxx.dao.UserDaoOracleImpl;
import com.xxx.service.UserService;
import com.xxx.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
//用户实际调用的是业务层,dao层他们不需要接触
UserServiceImpl service = new UserServiceImpl();
service.setUserDao( new UserDaoMysqlImpl() );
service.getUser();
//那我们现在又想用Oracle去实现呢
service.setUserDao( new UserDaoOracleImpl() );
service.getUser();
}
}
结果:
获取mysql的数据 获取Oracle的数据 进程已结束,退出代码为 0
- 之前,程序通过new主动创建对象!控制权在程序猿手上
- 使用set注入后,程序不再具有主动性,而是变成了被动的接受对象!
- 这种思想,从本质上解决了问题,程序员不用再去管理对象的创建了,降低了耦合性!
控制反转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)。
4.HelloSpring新建一个空模块spring-02-hellospring
地址:src/main/java/com/hello/pojo/Hello.java
代码:
package com.hello.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + ''' +
'}';
}
}
2. 编写我们的spring文件 , 这里我们命名为beans.xml
地址:src/main/resources/beans.xml
代码:
3.测试
import com.hello.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取spring上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在spring中管理了,我们要使用,直接去里面取出来就可以
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
结果:
Hello{str='Spring'}
进程已结束,退出代码为 0
会发现,已经不需要手动new对象,对象是在xml文件中配置。或者通俗来讲,不需要改底层代码,而xml文件不算底层代码。
控制反转
- 控制: 谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的
- 反转: 程序本身不创建对象,而变成被动的接收对象。
- 依赖注入: 就是利用set方法来进行注入的
- IOC是一种编程思想,由主动的编程变为被动的接收,所谓的IOC,即对象由Spring来创建,管理,装配
路径:src/main/resources/beans.xml
代码:
2. 测试
代码:
import com.xxx.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTestBean {
public static void main(String[] args) {
//获取ApplicationContext;拿到spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//需要什么就直接get
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
userServiceImpl.getUser();
}
}
结果:
获取mysql的数据 进程已结束,退出代码为 0
OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
6. IOC创建对象的方式新建一个空模块spring-03-ioc2
- 使用无参构造创建对象,默认
- 假设使用有参构造创建对象
地址:src/main/java/com/two/pojo/User.java
代码:
package com.two.pojo;
public class User {
private String name;
public User(){
System.out.println("USER 的无参构造");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("name = " + name);
}
}
2. 创建beans.xml
地址:src/main/resources/beans.xml
代码:
3. 测试
import com.two.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.show();
}
}
结果:
USER 的无参构造 name = jva 进程已结束,退出代码为 02. 使用有参构造创建对象 1. 下标赋值 Constructor argument index
2. 变量类型赋值 Constructor argument type matching 不建议使用
3.变量名称赋值 Constructor argument name
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了
三、Spring的基础配置 1. 别名 1. 配置别名
2. 使用别名
import com.two.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("userNew");
user.show();
}
}
运行结果
name = ss 进程已结束,退出代码为 02. Bean的配置 1. 新建实体类
地址:src/main/java/com/two/pojo/UserT.java
代码:
package com.two.pojo;
public class UserT {
private String name;
public UserT() {
System.out.println("UserT 的无参构造");
}
public UserT(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("name = " + name);
}
}
2.写beans.xml配置
地址:src/main/resources/beans.xml
代码:
3.测试
import com.two.pojo.User;
import com.two.pojo.UserT;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserT user = (UserT) context.getBean("u2");
user.show();
}
}
结果:
UserT 的无参构造 name = 黑心白莲 进程已结束,退出代码为 03.import
1. 导入代码这个import。一般用于团队开发使用,它可以将多个配置文件,导入合并为一个。
假设,现在项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
张三
李四
王五
applicationContext.xml
地址:src/main/resources/applicationContext.xml
代码:
使用的时候,直接使用总的配置就可以了。
四、DI依赖注入 1.构造器注入2.Set方式注入【重点】前面已经介绍过,参考 2.6 IOC创建对象的方式
依赖注入:Set注入
依赖:bean对象的创建依赖于容器!
注入:bean对象中的所有属性,由容器来注入!
复杂类型
地址:src/main/java/com/di/pojo/Address.java
代码:
package com.di.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
1. Student创建
真实测试对象
地址:src/main/java/com/di/pojo/Student.java
代码:
package com.di.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List hobbys;
private Map card;
private Set games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List getHobbys() {
return hobbys;
}
public void setHobbys(List hobbys) {
this.hobbys = hobbys;
}
public Map getCard() {
return card;
}
public void setCard(Map card) {
this.card = card;
}
public Set getGames() {
return games;
}
public void setGames(Set games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", address=" + address.getAddress() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + ''' +
", info=" + info +
'}';
}
}
2. bean配置文件创建
beans.xml
地址:src/main/resources/beans.xml
代码:
3.测试类创建
地址:src/test/java/MyTest.java
代码:
import com.di.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
测试结果:
lili 进程已结束,退出代码为 02.完善注入信息
完善注入信息
代码:
红楼梦 西游记 水浒传 三国演义
听歌 看电影 旅游 睡觉 LOL COC BOB 2012456 男 小明
测试:
import com.di.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
}
3.拓展方式注入
1. p命名注入
命名空间注入,可以直接注入属性的值。无需构造器
1. 新建实体类User.java :【注意:这里没有有参构造器!】
地址:src/main/java/com/di/pojo/User.java
代码:
package com.di.pojo;
public class User {
private String name;
private int age;
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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
2. 新建userbean.xml
引入p注入:xmlns:p="http://www.springframework.org/schema/p"
地址:src/main/resources/userbeans.xml
代码:
3. 测试
代码:test2
import com.di.pojo.Student;
import com.di.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
//指定class,就不用转换了
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
结果:
User{name='zhangsan', age=18}
进程已结束,退出代码为 0
2. c命名注入
通过构造器注入,必须有构造器
1. 修改实体类User.java :通过构造器注入,必须有构造器
地址:src/main/java/com/di/pojo/User.java
代码:
package com.di.pojo;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
2.userbean.xml添加
添加c注入代码:xmlns:c="http://www.springframework.org/schema/c"
地址:src/main/resources/userbeans.xml
代码:
3.测试
代码:test3
import com.di.pojo.Student;
import com.di.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
}
结果:
User{name='kk', age=18}
进程已结束,退出代码为 0
4.bean的作用域
五、Bean的自动装配
六、代理模式
七、AOP
八、整合Mybatis
九、Spring配置声明事务注入


