超全超细的Spring学习笔记

2024-02-25 21:10

本文主要是介绍超全超细的Spring学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

超全超细的Spring学习笔记

  • Spring简介
  • Spring使用
  • 控制反转(IOC)
    • 实现原理
    • IOC与传统方式的比较
    • IOC XML 开发
      • Bean标签配置
      • 生命周期
      • 作用范围
      • Spring工厂类
      • IOC和DI
      • 普通类型(简单类型)的set注入
      • 引用类型的set注入
      • 构造注入
      • 引用类型的自动注入
        • byName(按名称注入)
        • byType(按类型注入)
      • p名称空间的属性注入
      • SpEL(Spring Expression Language)属性注入(Spring 3.x以上版本)
      • 集合类型属性注入
      • 多模块开发设置
    • IOC注解开发
      • 注解详解
        • 1.Component
        • 2.属性注入
        • 3.其它注解
      • IOC的XML和注解开发比较
      • @Component:创建对象
      • @Value:简单类型的属性赋值
      • @Autowire:引用类型的byType自动注入
      • @Autowire+@Qualifier:引用类型的ByNama自动注入
      • @Resource:引用类型赋值(来自JDK)
  • AOP开发
    • 底层实现
      • JDK代理
      • Cglib代理
    • Spring 的 AOP 开发(AspectJ 的 XML 方式)
      • 相关术语
      • 使用方法
    • 通知类型
      • 前置通知
      • 后置通知
      • 环绕通知
      • 异常抛出通知
      • 最终通知
    • Spring 切入点表达式
    • Spring 的 AOP 基于 AspectJ 注解开发
      • 开发步骤
    • 注解通知类型
      • @Before:前置通知
      • @AfterReturning: 后置通知
      • @Around:环绕通知
      • @AfterThrowing: 抛出异常
      • @After: 最终通知
      • @PointCut:切入点注解
  • Spring的JDCB模板
    • 使用JDBC模板
    • 使用开源数据库连接池
    • CRUD操作
  • Spring的事务管理
    • 事务管理API
    • 事务的传播行为
    • 实例
    • 事务管理1:编程式事务管理
    • 声明式事务管理(配置实现,基于AOP思想)
    • 深入理解Spring事务原理
      • 一、事务的基本原理
      • 二、事务的传播属性
      • 三、数据库的隔离级别
      • 四、Spring中的隔离级别
      • 五、事务的嵌套
        • PROPAGATION_REQUIRED(spring 默认)
        • PROPAGATION_REQUIRES_NEW
        • PROPAGATION_SUPPORTS
        • PROPAGATION_NESTED
      • 六、总结
  • Spring整合MyBatis

Spring简介

Spring 是一个开源框架,是一个分层的 JavaEE 一站式框架。

所谓一站式框架是指 Spring 有 JavaEE 开发的每一层解决方案。

  • WEB层:SpringMVC
  • Service层:Spring的Bean管理,声明式事务
  • DAO层:Spring的JDBC模板,ORM模板

优点:

  • IOC:方便解耦合
  • AOP:对程序进行扩展
  • 轻量级框架
  • 方便与其他框架整合

Spring使用

Spring开发包解压后的目录介绍:

  • docs: Spring 开发规范和API
  • libs: Spring jar 包和源代码
  • schema: Spring 配置文件的约束

图片

DataAccess 用于数据访问,WEB 用于页面显示,核心容器也就是IOC部分。

控制反转(IOC)

控制反转(Inversion of Control)是指将对象的创建权反转(交给)Spring。

使用IOC就需要导入IOC相关的包,也就是上图中核心容器中的几个包:beans,context,core,expression四个包。

实现原理

传统方式创建对象

UserDao userDao = new UserDao();	

若进一步面向接口编程的话,可以多态:

UserDao userDao = new UserDaoImpl();

这种方式的缺点是接口和实现类高耦合,切换底层实现类时,需要修改源代码。程序设计应该满足OCP元祖,在尽量不修改程序源代码的基础上对程序进行扩展。

此时,学过设计模式的同学可能会想到用工厂模式对接口及其实现类进行解耦,我们使用工厂模式:

class BeanFactory{public static UserDAO getUserDAO(){return new UserDAOImpl();}
}

此种方式虽然在接口和实现类之间没有耦合,但是接口和工厂之间存在耦合。

使用工厂+反射+配置文件的方式,实现解耦,这也是 Spring 框架 IOC 的底层实现。

//xml配置文件
//<bean id="userDAO" class="xxx.UserDAOImpl"></bean>
class BeanFactory{public static Object getBean(String id){//解析XML//反射Class clazz=Class.forName();return clazz.newInstance();}
}

IOC与传统方式的比较

获取对象方式:传统通过 new 关键字主动创建一个对象。

IOC 方式中,将对象的生命周期交给 Spring 管理,直接从 Spring 获取对象。也就是控制反转————将控制权从自己手中交到了 Spring 手中

IOC XML 开发

在 docs 文件中包含了 xsd-configuration.hmtl 文件。其中定义了 beans schema。

<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<bean id="userService" class="x.y.UserServiceImpl"></bean>
</beans>

调用类:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("userService");
userService.save();

Bean标签配置

告诉spring创建对象

声明bean,就是告诉spring要创建某个类的对象

id:对象的自定义名称,唯一值,不能出现特殊字符。spring通过这个名称找到对象

class:类的全限定名称(不能是接口,因为spring是反射机制创建类,必须使用类)

spring就完成SomeService someService = new SomeServiceImpl();

spring是把创建好的对象放入到map中,spring框架有一个map存放对象的

springMap.put(id的值,对象);

​ 例如:springMap.put("someService",new SomeServiceImpl());

一个bean标签声明一个对象

生命周期

  • init-method: bean被初始化的时候执行的方法
  • destroy-method: bean被销毁的时候执行的方法

作用范围

scope:bean的作用范围,有如下几种,常用的是前两种

  1. singleton: 默认使用单例模式创建
  2. prototype: 多例
  3. request: 在web项目中,spring 创建类后,将其存入到 request 范围中
  4. session: 在web项目中,spring 创建类后,将其存入到 session 范围中
  5. globalsession: 在web项目中,必须用在 porlet 环境

Spring工厂类

  • BeanFactory: 老版本的工厂类,在调用getBean()方法时,才会生成类的实例。

  • ApplicationContext: 在加载配置文件的时候,就会将 Spring 管理的类都实例化。有两个实现类:

    1. ClassPathXmlApplicationContext: 加载类路径下的配置文件
    2. FileSystemXmlApplicationContext: 加载磁盘下的配置文件

IOC和DI

DI 指依赖注入,其前提是必须有 IOC 的环境,Spring 管理这个类的时候将类的依赖的属性注入进来。

例如,在UserServiceImpl.java中:

public class UserServiceImpl implements UserService{private String name;public void setName(String name){this.name=name;}public void save(){System.out.println("save "+name);}
}

在配置文件中:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"<bean id="userService" class="spring.demo1.UserServiceImpl"><!--配置依赖的属性--><property name="name" value="tony"/></bean>
</beans>

测试代码:

@Test
public void demo2(){//创建Spring工厂ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService=(UserService)applicationContext.getBean("userService");userService.save();
}

运行结果:

save tony

可以看到,在配置文件中配置的属性,在 Spring 管理该类的时候将其依赖的属性成功进行了设置。如果不使用依赖注入,则无法使用接口,只能使用实现类来进行设置,因为接口中没有该属性。

普通类型(简单类型)的set注入

在Spring中规定,Java的基本数据类型和String类型都是简单类型

set注入(设置注入):spring调用类的set方法,可以在set方法中完成属性赋值

简单类型的set注入:

<bean id="xx" class="xx"><property name="属性名字" value="此属性的值"/>一个property只能给一个属性赋值
</bean>

我们以Student类为例

在Student.java中:

public class Student {private String name;private int age;private School school;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setSchool(School school) {this.school = school;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", school=" + school +'}';}
}

在applicationContext.xml文件中:

<bean id="myStudent" class="com.jiawen.package1.Student"><property name="name" value="lisi"/><property name="age" value="20"/>
</bean>

测试:

@Test
public void test01(){String config = "package1/applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);Student myStudent = (Student) applicationContext.getBean("myStudent");System.out.println(myStudent);
}

运行结果:

Student{name='lisi', age=20}

引用类型的set注入

引用类型的set注入:spring调用类的set方法

<bean id="xxx" class="xxxx"><property name="属性名称" ref="bean的id(对象的名称)"/>
</bean>

以学校和学生为例

在School.java中:

public class School {private String name;private String address;public void setName(String name) {this.name = name;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "School{" +"name='" + name + '\'' +", address='" + address + '\'' +'}';}
}

在Student.java中:

public class Student {private String name;private int age;private School school;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setSchool(School school) {this.school = school;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", school=" + school +'}';}
}

在applicationContext.xml中:

<bean id="myStudent" class="com.jiawen.package2.Student"><property name="name" value="lisi"/><property name="age" value="22"/><property name="school" ref="mySchool"/></bean><!--    声明school对象--><bean id="mySchool" class="com.jiawen.package2.School"><property name="name" value="bj"/><property name="address" value="hdq"/></bean>

运行结果:

Student{name='lisi', age=22, school=School{name='bj', address='hdq'}}

构造注入

构造注入:spring调用类的有参构造方法,在创建对象的同时,在构造方法中属性赋值

构造注入使用<constructor-arg>标签

<constructor-arg>标签:一个<constructor-arg>表示构造方法的一个参数

<constructor-arg>标签属性:

​ name:表示构造方法的形参名

​ index:构造方法参数的位置,参数从左往右位置是0、1、2…的顺序

​ value:构造方法的形参类型是简单类型的,使用value

​ ref:构造那个方法的形参类型是引用类型的,使用ref

以学校和学生为例

在School.java中:

public class School {private String name;private String address;public void setName(String name) {this.name = name;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "School{" +"name='" + name + '\'' +", address='" + address + '\'' +'}';}
}

在Student.java中:

public class Student {private String name;private int age;private School school;public Student() {}public Student(String name, int age, School school) {this.name = name;this.age = age;this.school = school;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setSchool(School school) {this.school = school;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", school=" + school +'}';}
}

在applicationContext.xml中:

<bean id="myStudent" class="com.jiawen.package3.Student"><constructor-arg name="name" value="zhangsan"/><constructor-arg name="age" value="20"/><constructor-arg name="school" ref="mySchool"/>
</bean><bean id="mySchool" class="com.jiawen.package3.School"><property name="name" value="bj"/><property name="address" value="bjhd"/>
</bean>

测试:

@Test
public void test03(){String config = "package3/applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);Student myStudent = (Student) applicationContext.getBean("myStudent");System.out.println(myStudent);
}

运行结果:

Student{name='zhangsan', age=20, school=School{name='bj', address='bjhd'}}

引用类型的自动注入

引用类型的自动注入:spring框架根据某些规则可以给引用类型赋值
使用规则:byName,byType

byName(按名称注入)

byName(按名称注入):Java类中引用类型的属性名和spring容器中(配置文件)的id名称一样,且数据类型是一样的
这样的容器中的bean,spring能够赋值给引用类型
语法:

<bean id="xx" class="xx" autowire="byName">简单类型属性赋值
</bean>

以学校和学生为例

在School.java中:

public class School {private String name;private String address;public void setName(String name) {this.name = name;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "School{" +"name='" + name + '\'' +", address='" + address + '\'' +'}';}
}

在Student.java中:

public class Student {private String name;private int age;private School school;public Student() {}public Student(String name, int age, School school) {this.name = name;this.age = age;this.school = school;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setSchool(School school) {this.school = school;}

这篇关于超全超细的Spring学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/746725

相关文章

springboot项目中集成shiro+jwt完整实例代码

《springboot项目中集成shiro+jwt完整实例代码》本文详细介绍如何在项目中集成Shiro和JWT,实现用户登录校验、token携带及接口权限管理,涉及自定义Realm、ModularRe... 目录简介目的需要的jar集成过程1.配置shiro2.创建自定义Realm2.1 LoginReal

SpringBoot集成Shiro+JWT(Hutool)完整代码示例

《SpringBoot集成Shiro+JWT(Hutool)完整代码示例》ApacheShiro是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,在现代应用开发中,Shiro因... 目录一、背景介绍1.1 为什么使用Shiro?1.2 为什么需要双Token?二、技术栈组成三、环境

Java 与 LibreOffice 集成开发指南(环境搭建及代码示例)

《Java与LibreOffice集成开发指南(环境搭建及代码示例)》本文介绍Java与LibreOffice的集成方法,涵盖环境配置、API调用、文档转换、UNO桥接及REST接口等技术,提供... 目录1. 引言2. 环境搭建2.1 安装 LibreOffice2.2 配置 Java 开发环境2.3 配

在 Spring Boot 中连接 MySQL 数据库的详细步骤

《在SpringBoot中连接MySQL数据库的详细步骤》本文介绍了SpringBoot连接MySQL数据库的流程,添加依赖、配置连接信息、创建实体类与仓库接口,通过自动配置实现数据库操作,... 目录一、添加依赖二、配置数据库连接三、创建实体类四、创建仓库接口五、创建服务类六、创建控制器七、运行应用程序八

基于Spring Boot 的小区人脸识别与出入记录管理系统功能

《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型... 目录系统功能概述技术栈选择核心依赖配置数据模型设计出入记录实体类出入记录查询表单出入记录 VO 类(用于

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

Java中数组与栈和堆之间的关系说明

《Java中数组与栈和堆之间的关系说明》文章讲解了Java数组的初始化方式、内存存储机制、引用传递特性及遍历、排序、拷贝技巧,强调引用数据类型方法调用时形参可能修改实参,但需注意引用指向单一对象的特性... 目录Java中数组与栈和堆的关系遍历数组接下来是一些编程小技巧总结Java中数组与栈和堆的关系关于

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决

SpringBoot实现虚拟线程的方案

《SpringBoot实现虚拟线程的方案》Java19引入虚拟线程,本文就来介绍一下SpringBoot实现虚拟线程的方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录什么是虚拟线程虚拟线程和普通线程的区别SpringBoot使用虚拟线程配置@Async性能对比H

javaSE类和对象进阶用法举例详解

《javaSE类和对象进阶用法举例详解》JavaSE的面向对象编程是软件开发中的基石,它通过类和对象的概念,实现了代码的模块化、可复用性和灵活性,:本文主要介绍javaSE类和对象进阶用法的相关资... 目录前言一、封装1.访问限定符2.包2.1包的概念2.2导入包2.3自定义包2.4常见的包二、stati