Spring5-2021.8.5
1、Spring
1.1、简介
-
Spring框架是由于软件开发的复杂性而创建的
-
Spring的形成,最初来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,就是在这本书中第一次出现了Spring的一些核心思想,该书出版于2002年。
-
spring框架即以interface21框架为基础,经过重新设计,不断丰富其内涵,于2004年3月24发布了1.0正式版
-
**Rod Jahnson:**Spring框架的创始人,同时也是SpringSource的联合创始人。Spring是面向切面编程(AOP)和控制反转(IoC)的容器框架。Rod的畅销书Expert One-on-One J2EE Design and Development(2002年出版)是迄今为止J2EE领域最具影响力的书之一。
-
spring理念:使现有技术更加容易使用,本身是一个大杂烩,整合了现有技术框架
-
SSH:Struct + Spring + Hibernate
-
SSM:SpringMvc +Spring + Mybatis
官网:https://spring.io/projects/spring-framework
中文文档:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference
官方下载地址:http://repo.spring.io/release/org/springframework/spring
GitHub:
spring官方各版本jar包:https://www.cnblogs.com/borter/p/9543583.html
1.2、优点和弊端
- spring是一个开源的免费的框架(容器)
- spring是一个轻量级,非入侵式的框架
- 控制反转(IOC),面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
总结:spring是一个轻量级的控制反转(IOC)和面向切面编程的框架
**弊端:**由于发展太久,配置繁琐
1.3、组成
1.4、拓展
在spring的官网有这个介绍:现代化的Java开发就是基于spring的开发
- spring boot–> spring cloud–> spring cloud data flow
- 构建一切 --> 协调一切 --> 连接一切
spring boot
- 一个快速开发的脚手架
- 基于spring boot可以快速开发单个微服务
- 约定大于配置
spring cloud
- springcloud是基于spring boot实现的
现在大多数公司都在使用spring boot进行快速开发,学习spring boot的前提,需要完全掌握spring及springMVC(承上启下的作用)
2、IOC理念
1、导入依赖
报错:Cannot resolve org.springframework:spring-web:5.2.0.RELEASE
**分析:**依赖没删干净,或换成其他版本依赖
2、思想
-
之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改源代码,如果代码量十分大,修改一次成本代价十分昂贵
-
我们使用一个set接口实现,已经发生了革命性的变化
private UserDao userdao;
//利用set进行动态实现值得注入!
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
-
之前,程序主动创建对象!控制权在程序员手上
使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象(主动权在用户手里)
3、IOC本质
https://mp.weixin.qq.com/s/VM6INdNB_hNfXCMq3UZgTQ
- 控制反转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
1、导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.8</version>
</dependency>
2、编写代码
- 编写一个Hello实体类
package com.xdy.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 + '\'' +
'}';
}
}
- 编写spring文件,这里命名为beans.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">
<!-- 这里就相当于spring的容器,事情交给它做,用时拿它就行-->
<!-- 使用spring创建对象,在spring这些都称为Bean
以前:类型 变量名 = new 类型();
Hello hello = new Hello()
现在:id = 变量名 class = new的对象
property value相当于给对象中的属性设置一个值
-->
<bean id="hello" class="com.xdy.pojo.Hello">
<!-- 给str赋值-->
<property name="str" value="Spring"/>
</bean>
</beans>
- 测试
import com.xdy.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Mytest {
public static void main(String[] args) {
//获取ApplicationContext:拿到spring的容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在spring中管理了,要使用直接去里面取出来就可以
//hello是从容器中拿出来的
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
思考问题 ?
Hello 对象是谁创建的 ?
hello 对象是由Spring创建的
Hello 对象的属性是怎么设置的 ?
hello 对象的属性是由Spring容器设置的 ,
这个过程就叫控制反转 :
控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 .
反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想 , 由主动的编程变成被动的接收 .
可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .
OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
5、IOC创建对象的方式
1、默认使用无参构造创建对象
2、假设我们要使用有参构造创建对象
- 下标赋值
<!--第一种,下标赋值-->
<bean id="user" class="com.xdy.pojo.User">
<constructor-arg index="0" value="xdy"/>
</bean>
报错:Cannot find constructor with argument index 0 in class com.xdy.pojo.User 在类com.xdy.pojo.User中找不到参数索引为0的构造函数
分析:实体类中没有写有参构造
public User(String name) {
this.name = name;
}
- 类型创建
<!--第二种,通过类型创建,如果有两个相同类型,就不好赋值,所以不建议使用-->
<bean id="user" class="com.xdy.pojo.User">
<constructor-arg type="java.lang.String" value="oi"/>
</bean>
- 参数名创建
<!--第三种,直接通过参数名创建-->
<bean id="user" class="com.xdy.pojo.User">
<constructor-arg name="name" value="发"/>
</bean>
6、spring配置
6.1、别名
<!--别名:如果添加了别名,也可以通过别名获取到这个对象-->
<alias name="user" alias="user2"/>
6.2、bean的配置
<!--
id:bean的唯一标识符,相当于我们学的对象名
class:bean对象所对应的全限定名:包名+类型
name:别名,而且name可以同时取多个别名,还可用不同符号隔开
-->
<bean id="user" class="com.xdy.pojo.User" name="user2 u2,u3;u4">
<constructor-arg value="name"/>
<property name="name" value="df"/>
</bean>
6.3、import
-
一般用于团队开发使用,可以将多个配置文件,导入合并为一个
-
假设项目有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的
-
张三
-
李四
-
王五
-
applicationContext.xml
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
使用的时候,直接使用总配置即可
7、DI依赖注入环境
7.1、构造器注入
7.2、set方式注入【重点】
-
依赖注入本质是:set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象的所有属性,由容器来注入!
-
环境搭建
- 复杂类型
package com.xdy.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
- 真实测试对象
package com.xdy.pojo; import java.util.*; public class Student { private String name; private Address address ; private String[] book; private List<String> hobbys; private Map<String,String> card; private Set<String> 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[] getBook() { return book; } public void setBook(String[] book) { this.book = book; } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> 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 "Address{" + "name='" + name + '\'' + ", address=" + address + ", book=" + Arrays.toString(book) + ", hobbys=" + hobbys + ", card=" + card + ", games=" + games + ", wife='" + wife + '\'' + ", info=" + info + '}'; } }
- beans.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 id="student" class="com.xdy.pojo.Student"> <!--第一种:普通值注入,通过value --> <property name="name" value="小薛"/> </bean> </beans>
- 测试
import com.xdy.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