Spring学习笔记01

1.Spring概述

1.1 简介

Spring学习笔记01 - 图1

Spring :春天——> 给软件行业带来了春天

2002年,Rob Jahnson首次推出了Spring框架原型interface21框架

2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版

Spring理念:使现有技术更加实用,整合现有的框架技术

官网:https://spring.io/

官方文档: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/

官方下载地址:https://repo.spring.io/release/org/springframework/spring/

GitHub地址:https://github.com/spring-projects/spring-framework

优点:

  • Spring是一个免费开源的框架,容器
  • spring是一个轻量级的框架,非侵入式的
  • 控制反转IoC 面向切面 Aop
  • 对事务的支持,对框架的支持

总结:Spring是一个轻量级的控制反转(IoC)和面向切面(Aop)的容器(框架)

1.2 组成

Spring学习笔记01 - 图2

Spring框架是一个分层架构,由7个定义良好的模块组成,Spring模块构建在核心容器之上,核心容器定义了创建,配置,和管理bean的方式

Spring学习笔记01 - 图3

组成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、iText和POI

1.3 拓展

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,属于依赖的关系
  • Spring Boot 在SpringCloud中起到了承上启下的作用,如果要学习Spring Cloud 必须要学习Spring Boot

2.IOC理论指导

2 .1 IOC基础

新建一个maven项目

先用之前的方式写一个项目

1.先写一个UserDao 接口

  1. package com.jcsune.dao;
  2. public interface UserDao {
  3. void getUser();
  4. }

2.再去写Dao的实现类

  1. package com.jcsune.dao;
  2. public class UserDaoImpl implements UserDao {
  3. public void getUser() {
  4. System.out.println("默认获取用户的数据");
  5. }
  6. }

3.接着写UserService的接口

  1. package com.jcsune.service;
  2. public interface UserService {
  3. public void getUser();
  4. }

4.接着写UseService的实现类

  1. package com.jcsune.service;
  2. import com.jcsune.dao.UserDao;
  3. import com.jcsune.dao.UserDaoImpl;
  4. public class UserServiceImpl implements UserService{
  5. private UserDao userDao=new UserDaoImpl() ;
  6. public void getUser() {
  7. userDao.getUser();
  8. }
  9. }

5.测试

  1. import com.jcsune.service.UserService;
  2. import com.jcsune.service.UserServiceImpl;
  3. import org.junit.Test;
  4. public class MyTest {
  5. @Test
  6. public void test() {
  7. UserService service= new UserServiceImpl();
  8. service.getUser();
  9. }
  10. }

6.运行结果

Spring学习笔记01 - 图4

7.如果我们把UserDao的实现类增加一个UserDaoMysqlImpl

  1. package com.jcsune.dao;
  2. public class UserDaoMysqlImpl implements UserDao {
  3. public void getUser() {
  4. System.out.println("Mysql获取用户数据");
  5. }
  6. }

8.我们如果要去使用Mysql的话,我们就需要去service的实现类里面修改对应的实现

  1. import com.jcsune.dao.UserDao;
  2. import com.jcsune.dao.UserDaoImpl;
  3. import com.jcsune.dao.UserDaoMysqlImpl;
  4. public class UserServiceImpl implements UserService{
  5. /*private UserDao userDao=new UserDaoImpl() ;*/
  6. private UserDao userDao=new UserDaoMysqlImpl();
  7. public void getUser() {
  8. userDao.getUser();
  9. }
  10. }

9.测试结果(这时测试代码不用修改)

Spring学习笔记01 - 图5

接着如果我们要使用Oracle,又需要去service实现类里面修改对应的实现万一需求大的话,这种方式根本不适用,耦合性太高,牵一发儿动全身

10.解决方法

  • 首先新增一个UserDao的实现类UserDaoOracleImpl
  1. package com.jcsune.dao;
  2. public class UserDaoOracleImpl implements UserDao {
  3. public void getUser() {
  4. }
  5. }
  • 我们在需要用到它的地方,不去实现它,而是留出一个接口,利用set
  1. package com.jcsune.service;
  2. import com.jcsune.dao.UserDao;
  3. import com.jcsune.dao.UserDaoImpl;
  4. import com.jcsune.dao.UserDaoMysqlImpl;
  5. public class UserServiceImpl implements UserService{
  6. /*private UserDao userDao=new UserDaoImpl() ;*/
  7. /*private UserDao userDao=new UserDaoMysqlImpl();*/
  8. private UserDao userDao;
  9. //利用set实现
  10. public void setUserDao(UserDao userDao) {
  11. this.userDao = userDao;
  12. }
  13. public void getUser() {
  14. userDao.getUser();
  15. }
  16. }
  • 最后去测试类中进行测试(此时测试代码需要更改)
  1. import com.jcsune.dao.UserDaoOracleImpl;
  2. import com.jcsune.service.UserService;
  3. import com.jcsune.service.UserServiceImpl;
  4. import org.junit.Test;
  5. public class MyTest {
  6. @Test
  7. public void test() {
  8. UserService service= new UserServiceImpl();
  9. service.setUserDao(new UserDaoOracleImpl());
  10. service.getUser();
  11. }
  12. }

Spring学习笔记01 - 图6

没使用set之前,所有的东西都是由程序去进行控制创建,而使用set之后由我们自行控制创建对象,把主动权交给了调用者,程序不用去管怎么创建,怎么实现的了,它只负责提供一个接口,这种思想从本质上解决了问题,程序员不用去管对象的创建的了,更多的去关注业务的实现,耦合性大大降低,这也就是IOC的原型

2.2 IOC本质

控制反转 IoC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现IOC的一种方法,在没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序里,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,所谓的控制反转就是获得依赖对象的方式反转了

IOC是Spring框架的核心内容,使用多种方式完美实现了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IOC

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时在从Ioc容器中取出需要的对象

Spring学习笔记01 - 图7

采用XML方式配置Bean的时候,Bean的定义信息和实现是分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入

3.HelloSpring

3.1 HelloSpring

新建一个maven项目,导入jar包

注:Spring需要导入commons-logging进行日志记录,我们利用maven,它会自动下载对应的依赖项

  1. <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-webmvc</artifactId>
  5. <version>5.1.10.RELEASE</version>
  6. </dependency>

1.编写一个Hello实体类

  1. package com.jcsune.pojo;
  2. public class Hello {
  3. private String name;
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. public void show(){
  11. System.out.println("Hello,"+name);
  12. }
  13. }

2.编写spring文件,这里我们可以命名为beans.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--bean就是java对象,由Spring创建和管理-->
  7. <bean id="hello" class="com.jcsune.pojo.Hello">
  8. <property name="name" value="Spring"/>
  9. </bean>
  10. </beans>

3.进行测试

  1. import com.jcsune.pojo.Hello;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. public class MyTest {
  5. public static void main(String[] args) {
  6. //解析beans.xml文件,生成管理对应的Bean对象
  7. ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  8. //getBean:参数即为spring配置文件中bean的id
  9. Hello hello=(Hello) context.getBean("hello");
  10. hello.show();
  11. }
  12. }

4.结果

Spring学习笔记01 - 图8

思考

  • Hello对象是由谁创建的? 答:Hello对象是由Spring创建的
  • Hello对象的属性是怎么设置的? 答:hello对象的属性是由Spring容器设置的,这个过程就叫控制反转
  • 控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的
  • 反转:程序本身不创建对象,而变成被动的接收对象

依赖注入:就是利用set方法来进行注入的

IoC是一种编程思想,由主动的编程变成被动的接收

3.2 IoC创建对象的方式

通过无参构造方法来创建

  1. User.java
  1. package com.jcsune.pojo;
  2. public class User {
  3. private String name;
  4. public User(){
  5. System.out.println("user无参构造方法");
  6. }
  7. public String getName() {
  8. return name;
  9. }
  10. public void setName(String name) {
  11. this.name = name;
  12. }
  13. public void show(){
  14. System.out.println("name="+name);
  15. }
  16. }
  1. beans.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="user" class="com.jcsune.pojo.User">
  7. <property name="name" value="jcsune"/>
  8. </bean>
  9. </beans>
  1. 测试类
  1. import com.jcsune.pojo.User;
  2. import org.junit.Test;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class MyTest {
  6. @Test
  7. public void test(){
  8. ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  9. //在执行getBean的时候,user已经创建好了,通过无参构造
  10. User user = (User)context.getBean("user");
  11. //调用对象的方法
  12. user.show();
  13. }
  14. }
  1. 结果

Spring学习笔记01 - 图9

通过有参构造方法来编写

  1. UserT.java
  1. package com.jcsune.pojo;
  2. public class UserT {
  3. private String name;
  4. public UserT(String name){
  5. this.name=name;
  6. }
  7. public String getName() {
  8. return name;
  9. }
  10. public void setName(String name) {
  11. this.name = name;
  12. }
  13. public void show(){
  14. System.out.println("name="+name);
  15. }
  16. }
  1. bean.xml有三种方式来编写
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--<bean id="user" class="com.jcsune.pojo.User">-->
  7. <!-- <property name="name" value="jcsune"/>-->
  8. <!--</bean>-->
  9. <!-- 第一种根据index参数下标设置-->
  10. <bean id="userT" class="com.jcsune.pojo.UserT">
  11. <!-- index指构造方法,下标从0开始-->
  12. <constructor-arg index="0" value="jcsune2"/>
  13. </bean>
  14. <!-- 第二种根据参数名字来设置-->
  15. <bean id="userT" class="com.jcsune.pojo.UserT">
  16. <!-- name指参数名-->
  17. <constructor-arg name="name" value="jcsune2"/>
  18. </bean>
  19. <!-- 第三种根据参数类型设置-->
  20. <bean id="userT" class="com.jcsune.pojo.UserT">
  21. <constructor-arg type="java.lang.String" value="jcsune2"/>
  22. </bean>
  23. </beans>
  1. 测试
  1. @Test
  2. public void testT(){
  3. ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  4. UserT userT=(UserT)context.getBean("userT");
  5. userT.show();
  6. }
  1. 结果

Spring学习笔记01 - 图10

3.3 Spring配置

1. 别名

alias 设置别名,为bean设置别名,在获取bean的时候可以使用别名获取

  1. <alias name="userT" alias="ccsune"/>

2.Bean的配置

  1. <!--bean就是java对象,由Spring创建和管理-->
  2. <!--
  3. id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
  4. 如果配置id,又配置了name,那么name是别名
  5. name可以设置多个别名,可以用逗号,分号,空格隔开
  6. 如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
  7. class是bean的全限定名=包名+类名
  8. -->
  9. <bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
  10. <property name="name" value="Spring"/>
  11. </bean>

3.import

团队的合作使用import来实现,它可以把多个配置文件合并为一个

  1. <import resource="{path}/beans.xml"/>

4.依赖注入

4.1 概念

  • 依赖注入(Dependency Injectiojn, DI)
  • 依赖:指Bean对象的创建依赖于容器。 Bean对象的依赖资源
  • 注入: 指Bean对象所依赖的资源,由容器来设置和装配

4.2 构造器注入

见 3.2 IoC创建对象的方式

4.3 Set注入(重点)

要求被注入的属性,必须有set方法,set方法的方法名是由set+属性首字母大写,如果属性是boolean类型,没有set方法。是is

测试类:

Address.java

  1. package com.jcsune.pojo;
  2. public class Address {
  3. private String address;
  4. public String getAddress() {
  5. return address;
  6. }
  7. public void setAddress(String address) {
  8. this.address = address;
  9. }
  10. }

Student.java

  1. package com.jcsune.pojo;
  2. import java.util.*;
  3. public class Student {
  4. private String name;
  5. private Address address;
  6. private String[] books;
  7. private List<String> hobbies;
  8. private Map<String,String> card;
  9. private Set<String> games;
  10. private String wife;
  11. private Properties info;
  12. public String getName() {
  13. return name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public Address getAddress() {
  19. return address;
  20. }
  21. public void setAddress(Address address) {
  22. this.address = address;
  23. }
  24. public List<String> getHobbies() {
  25. return hobbies;
  26. }
  27. public void setHobbies(List<String> hobbies) {
  28. this.hobbies = hobbies;
  29. }
  30. public Map<String, String> getCard() {
  31. return card;
  32. }
  33. public void setCard(Map<String, String> card) {
  34. this.card = card;
  35. }
  36. public Set<String> getGames() {
  37. return games;
  38. }
  39. public void setGames(Set<String> games) {
  40. this.games = games;
  41. }
  42. public String getWife() {
  43. return wife;
  44. }
  45. public void setWife(String wife) {
  46. this.wife = wife;
  47. }
  48. public Properties getInfo() {
  49. return info;
  50. }
  51. public void setInfo(Properties info) {
  52. this.info = info;
  53. }
  54. public String[] getBooks() {
  55. return books;
  56. }
  57. public void setBooks(String[] books) {
  58. this.books = books;
  59. }
  60. @Override
  61. public String toString() {
  62. return "Student{" +
  63. "name='" + name + '\'' +
  64. ", address=" + address.getAddress() +
  65. ", books=" + Arrays.toString(books) +
  66. ", hobbies=" + hobbies +
  67. ", card=" + card +
  68. ", games=" + games +
  69. ", wife='" + wife + '\'' +
  70. ", info=" + info +
  71. '}';
  72. }
  73. }

beans.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="addr" class="com.jcsune.pojo.Address">
  7. <property name="address" value="河南"/>
  8. </bean>
  9. <bean id="student" class="com.jcsune.pojo.Student">
  10. <!-- 常量注入-->
  11. <property name="name" value="小明"/>
  12. <!-- Bean 注入-->
  13. <property name="address" ref="addr"/>
  14. <!-- 数组注入 -->
  15. <property name="books">
  16. <array>
  17. <value>西游记</value>
  18. <value>水浒传</value>
  19. <value>红楼梦</value>
  20. </array>
  21. </property>
  22. <!-- List注入 -->
  23. <property name="hobbies">
  24. <list>
  25. <value>听歌</value>
  26. <value>打游戏</value>
  27. </list>
  28. </property>
  29. <!-- Map注入-->
  30. <property name="card">
  31. <map>
  32. <entry key="中国邮政" value="5487745887"/>
  33. <entry key="建设银行" value="4448785884"/>
  34. </map>
  35. </property>
  36. <!-- Set注入-->
  37. <property name="games">
  38. <set>
  39. <value>LOL</value>
  40. <value>CF</value>
  41. </set>
  42. </property>
  43. <!-- Null注入-->
  44. <property name="wife"><null/></property>
  45. <!-- Properties注入-->
  46. <property name="info">
  47. <props>
  48. <prop key="学号">15401700214</prop>
  49. <prop key="性别"></prop>
  50. <prop key="姓名">小明</prop>
  51. </props>
  52. </property>
  53. </bean>
  54. </beans>

测试类

  1. import com.jcsune.pojo.Student;
  2. import org.junit.Test;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class MyTest {
  6. @Test
  7. public void test(){
  8. ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  9. Student student=(Student)context.getBean("student");
  10. System.out.println(student.toString());
  11. }
  12. }

运行结果:

Spring学习笔记01 - 图11

4.5 p命名和c命名注入

User.java

  1. package com.jcsune.pojo;
  2. public class User {
  3. private String name;
  4. private int age;
  5. public User() {
  6. }
  7. public User(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int id) {
  21. this.age= age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "User{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. }

beansuser.xml

Spring学习笔记01 - 图12

c就是所谓的构造器注入

测试:

  1. public void testT(){
  2. ApplicationContext context = new ClassPathXmlApplicationContext("beansuser.xml");
  3. User user=(User)context.getBean("user");
  4. System.out.println(user.toString());
  5. User user2=(User)context.getBean("user2");
  6. System.out.println(user2.toString());
  7. }

运行结果:

Spring学习笔记01 - 图13