云计算百科
云计算领域专业知识百科平台

Spring(全网最详细)值得收藏

Spring介绍

image-20230829151858869

什么是Spring

Spring是一个开源框架,为简化企业级开发而生。它以IOC(控制反转)和AOP(面向切面)为思想内核,提供了控制层SpringMVC、数据层SpringData、服务层事务管理等众多技术,并可以整合众多第三方框架。

Spring将很多复杂的代码变得优雅简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。

Spring官网地址:Spring | Home

Spring6版本介绍

2022年底,Spring正式发布Spring6,此时距离Spring5发布已经有四年多了。Spring6是一个跨越式的升级:

  • 整个框架支持的最低JDK版本直接跨越到 JDK17。

  • Servlet、JPA 等从javax迁移到jakarta命名空间。

  • 兼容jakarta EE 9 、jakarta EE 10。

  • 支持AOT技术。

  • Spring本次升级更多是为了SpringBoot升级到3.0做准备,我们也将在SpringBoot3.0中详细讲解AOT等新版的功能。

    实时效果反馈

    1. Spring的思想内核是

    A 控制反转和面向对象

    B 控制反转和面向过程

    C 控制反转和面向切面

    D 控制反转和面向接口

    答案

    1=>C

    Spring体系结构

    image-20211202103309145

    Spring框架根据不同的功能被划分成了多个模块,这些模块可以满足一切企业级应用开发的需求,在开发过程中可以根据需求有选择性地使用所需要的模块。

    • Core Container:Spring核心模块,任何功能的使用都离不开该模块,是其他模块建立的基础。

    • Data Access/Integration:该模块提供了数据持久化的相应功能。

    • Web:该模块提供了web开发的相应功能。

    • AOP:提供了面向切面编程实现

    • Aspects:提供与AspectJ框架的集成,该框架是一个面向切面编程框架。

    • Instrumentation:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。

    • Messaging:为Spring框架集成一些基础的报文传送应用

    • Test:提供与测试框架的集成

    实时效果反馈

    1. Spring的核心模块是

    A Core Container

    B Web

    C AOP

    D Data Access/Integration

    2. 关于Spring模块,说法正确的是

    A 在开发过程中必须使用所有模块

    B Test模块提供了web开发的相应功能

    C 任何功能的使用都离不开Spring核心模块

    D Web模块是Spring核心模块

    答案

    1=>A 2=>C

    IOC_控制反转思想

    image-20211126165759417

    IOC(Inversion of Control) :程序将创建对象的权利交给框架。

    之前在开发过程中,对象实例的创建是由调用者管理的,代码如下:

    public interface StudentDao {
    // 根据id查询学生
    Student findById(int id);
    }

    public class StudentDaoImpl implements StudentDao{
    @Override
    public Student findById(int id) {
    // 模拟从数据库查找出学生
    return new Student(1,\”百战程序员\”,\”北京\”);
    }
    }

    public class StudentService {
    public Student findStudentById(int id){
    // 此处就是调用者在创建对象
    StudentDao studentDao = new StudentDaoImpl();
    return studentDao.findById(1);
    }
    }

    这种写法有两个缺点:

  • 浪费资源:StudentService调用方法时即会创建一个对象,如果不断调用方法则会创建大量StudentDao对象。

  • 代码耦合度高:假设随着开发,我们创建了StudentDao另一个更加完善的实现类StudentDaoImpl2,如果在StudentService中想使用StudentDaoImpl2,则必须修改源码。

  • 而IOC思想是将创建对象的权利交给框架,框架会帮助我们创建对象,分配对象的使用,控制权由程序代码转移到了框架中,控制权发生了反转,这就是Spring的IOC思想。而IOC思想可以完美的解决以上两个问题。

    实时效果反馈

    1. IOC思想是将创建对象的权利交给

    A 调用者

    B 框架

    C 被调用者

    D JDK

    答案

    1=>B

    IOC_自定义对象容器

    image-20211124150748998

    接下来我们通过一段代码模拟IOC思想。创建一个集合容器,先将对象创建出来放到容器中,需要使用对象时,只需要从容器中获取对象即可,而不需要重新创建,此时容器就是对象的管理者。

  • 创建实体类

    public class Student {
    private int id;
    private String name;
    private String address;
    // 省略getter/setter/构造方法/tostring
    }

  • 创建Dao接口和实现类

    public interface StudentDao {
    // 根据id查询学生
    Student findById(int id);
    }

    public class StudentDaoImpl implements StudentDao {
    @Override
    public Student findById(int id) {
    // 模拟从数据库查找出学生
    return new Student(1,\”百战程序员\”,\”北京\”);
    }
    }

    public class StudentDaoImpl2 implements StudentDao {
    @Override
    public Student findById(int id) {
    // 模拟从数据库查找出学生
    System.out.println(\”新方法!!!\”);
    return new Student(1,\”百战程序员\”,\”北京\”);
    }
    }

  • 创建配置文件bean.properties,该文件中定义管理的对象

    studentDao=com.itbaizhan.dao.impl.StudentDaoImpl

  • 创建容器管理类,该类在类加载时读取配置文件,将配置文件中配置的对象全部创建并放入容器中。

    public class Container {
    static Map<String,Object> map = new HashMap<>();
    static {
    // 读取配置文件
    InputStream is = Container.class.getClassLoader().getResourceAsStream(\”bean.properties\”);
    Properties properties = new Properties();
    try {
    properties.load(is);
    } catch (IOException e) {
    throw new RuntimeException(e);
    }

    // 遍历配置文件的所有配置信息
    Enumeration<Object> keys = properties.keys();
    while (keys.hasMoreElements()){
    String key = keys.nextElement().toString();
    String value = properties.getProperty(key);
    try {
    // 创建对象,将对象放入集合
    Object o = Class.forName(value).newInstance();
    map.put(key,o);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    }

    // 从容器中获取对象
    public static Object getBean(String key){
    return map.get(key);
    }
    }

  • 创建Dao对象的调用者StudentService

    public class StudentService {
    public Student findStudentById(int id){
    StudentDao studentDao = (StudentDao) Container.getBean(\”studentDao\”);
    System.out.println(studentDao.hashCode());
    return studentDao.findById(id);
    }
    }

  • 测试StudentService

    public class Test {
    public static void main(String[] args) {
    StudentService studentService = new StudentService();
    System.out.println(studentService.findStudentById(1));
    System.out.println(studentService.findStudentById(1));
    }
    }

  • 测试结果:

  • StudentService从容器中每次拿到的都是同一个StudentDao对象,节约了资源。

  • 如果想使用StudentDaoImpl2对象,只需要修改bean.properties的内容为

    studentDao=com.itbaizhan.dao.StudentDaoImpl2

    即可,无需修改Java源码。

  • IOC_Spring实现IOC

    image-20211126170010941

    接下来我们使用Spring实现IOC,Spring内部也有一个容器用来管理对象。

  • 创建Maven工程,引入依赖

    <dependencies>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.0.11</version>
    </dependency>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
    </dependency>
    </dependencies>

  • 创建POJO类、Dao类和接口

    public class Student {
    private int id;
    private String name;
    private String address;
    // 省略getter/setter/构造方法/tostring
    }

    public interface StudentDao {
    // 根据id查询学生
    Student findById(int id);
    }

    public class StudentDaoImpl implements StudentDao{
    @Override
    public Student findById(int id) {
    // 模拟从数据库查找出学生
    return new Student(1,\”百战程序员\”,\”北京\”);
    }
    }

  • 编写xml配置文件,配置文件中配置需要Spring帮我们创建的对象。

    <?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=\”studentDao\” class=\”com.itbaizhan.dao.StudentDaoImpl\”></bean>

    </beans>

  • 测试从Spring容器中获取对象。

    public class TestContainer {
    @Test
    public void t1(){
    // 创建Spring容器
    ApplicationContext ac = new ClassPathXmlApplicationContext(\”bean.xml\”);
    // 从容器获取对象
    StudentDao studentDao1 = (StudentDao) ac.getBean(\”studentDao\”);
    StudentDao studentDao2 = (StudentDao) ac.getBean(\”studentDao\”);
    System.out.println(studentDao1.hashCode());
    System.out.println(studentDao2.hashCode());
    System.out.println(studentDao1.findById(1));
    }
    }

  • 实时效果反馈

    1. Spring配置文件中,通过配置标签配置容器中的对象

    A <beans>

    B <pojo>

    C <entity>

    D <bean>

    2. Spring配置文件中,<bean>标签的属性可以配置对象类型

    A id

    B name

    C class

    D value

    答案

    1=>D 2=>C

    IOC_Spring容器类型

    image-20211124165406979

    容器接口

    • BeanFactory:BeanFactory是Spring容器中的顶层接口,它可以对Bean对象进行管理。

    • ApplicationContext:ApplicationContext是BeanFactory的子接口。它除了继承 BeanFactory的所有功能外,还添加了对国际化、资源访问、事件传播等方面的良好支持。

      ApplicationContext有以下三个常用实现类:

    容器实现类

    • ClassPathXmlApplicationContext:该类可以从项目中读取配置文件

    • FileSystemXmlApplicationContext:该类从磁盘中读取配置文件

    • AnnotationConfigApplicationContext:使用该类不读取配置文件,而是会读取注解

    @Test
    public void t2(){
    // 创建spring容器
    // ApplicationContext ac = new ClassPathXmlApplicationContext(\”bean.xml\”);
    ApplicationContext ac = new FileSystemXmlApplicationContext(\”C:\\\\Users\\\\a\\\\IdeaProjects\\\\spring_demo\\\\src\\\\main\\\\resources\\\\bean.xml\”);

    // 从容器中获取对象
    StudentDao userDao = (StudentDao) ac.getBean(\”studentDao\”);
    System.out.println(userDao);
    System.out.println(userDao.findById(1));
    }

    实时效果反馈

    1. Spring容器的顶层接口是

    A BeanFactory

    B ApplicationContext

    C ClassPathXmlApplicationContext

    D FileSystemXmlApplicationContext

    2. 如果想从磁盘中读取配置文件,需要创建类型的Spring容器

    A ClassPathXmlApplicationContext

    B FileSystemXmlApplicationContext

    C AnnotationConfigApplicationContext

    D 以上都可以

    答案

    1=>A 2=>B

    IOC_对象的创建方式

    image-20211126171348088

    Spring会帮助我们创建bean,那么它底层是调用什么方法进行创建的呢?

    使用构造方法

    Spring默认使用类的空参构造方法创建bean:

    // 假如类没有空参构造方法,将无法完成bean的创建
    public class StudentDaoImpl implements StudentDao{
    public StudentDaoImpl(int a){}

    @Override
    public Student findById(int id) {
    // 模拟根据id查询学生
    return new Student(1,\”百战程序员\”,\”北京\”);
    }
    }

    使用工厂类的方法

    Spring可以调用工厂类的方法创建bean:

  • 创建工厂类,工厂类提供创建对象的方法:

    public class StudentDaoFactory {
    public StudentDao getStudentDao(){
    return new StudentDaoImpl(1);
    }
    }

  • 在配置文件中配置创建bean的方式为工厂方式。

    <!– id:工厂对象的id,class:工厂类 –>
    <bean id=\”studentDaoFactory\” class=\”com.itbaizhan.dao.StudentDaoFactory\”></bean>
    <!– id:bean对象的id,factory-bean:工厂对象的id,factory-method:工厂方法 –>
    <bean id=\”studentDao\” factory-bean=\”studentDaoFactory\” factory-method=\”getStudentDao\”></bean>

  • 测试

  • 使用工厂类的静态方法

    Spring可以调用工厂类的静态方法创建bean:

  • 创建工厂类,工厂提供创建对象的静态方法。

    public class StudentDaoFactory2 {
    public static StudentDao getStudentDao2() {
    return new StudentDaoImpl();
    }
    }

  • 在配置文件中配置创建bean的方式为工厂静态方法。

    <!– id:bean的id class:工厂全类名 factory-method:工厂静态方法 –>
    <bean id=\”studentDao\” class=\”com.itbaizhan.dao.StudentDaoFactory2\” factory-method=\”getStudentDao2\”></bean>

  • 测试

  • 实时效果反馈

    1. Spring不能使用创建bean对象

    A 静态工厂方法

    B 工厂方法

    C 空参构造方法

    D 有参构造方法

    2. Spring调用工厂类的普通方法创建bean需要配置

    A 工厂对象和被创建的对象

    B 工厂对象

    C 被创建的对象

    D 以上都可以

    答案

    1=>C 2=>A

    IOC_对象的创建策略

    image-20211126171610772

    Spring通过配置<bean>中的scope属性设置对象的创建策略,共有五种创建策略:

    • singleton:单例,默认策略。整个项目只会创建一个对象,通过<bean>中的lazy-init属性可以设置单例对象的创建时机:

      lazy-init=\”false\”(默认):立即创建,在容器启动时会创建配置文件中的所有Bean对象。

      lazy-init=\”true\”:延迟创建,第一次使用Bean对象时才会创建。

      配置单例策略:

      <!– <bean id=\”studentDao\” class=\”com.itbaizhan.dao.StudentDaoImpl2\” scope=\”singleton\” lazy-init=\”true\”></bean> –>
      <bean id=\”studentDao\” class=\”com.itbaizhan.dao.StudentDaoImpl2\” scope=\”singleton\” lazy-init=\”false\”></bean>

      测试单例策略:

      // 为Bean对象的类添加构造方法
      public StudentDaoImpl2(){
      System.out.println(\”创建StudentDao!!!\”);
      }

      @Test
      public void t2(){
      // 创建Spring容器
      ApplicationContext ac = new ClassPathXmlApplicationContext(\”bean1.xml\”);
      // 从容器获取对象
      StudentDao studentDao1 = (StudentDao) ac.getBean(\”studentDao\”);
      StudentDao studentDao2 = (StudentDao) ac.getBean(\”studentDao\”);
      StudentDao studentDao3 = (StudentDao) ac.getBean(\”studentDao\”);
      System.out.println(studentDao1.hashCode());
      System.out.println(studentDao2.hashCode());
      System.out.println(studentDao3.hashCode());
      }

    • prototype:多例,每次从容器中获取时都会创建对象。

      <!– 配置多例策略 –>

      <
      bean
      id=
      \”studentDao\”
      class=
      \”com.itbaizhan.dao.StudentDaoImpl2\”
      scope=
      \”prototype\”
      ></
      bean
      >

    • request:每次请求创建一个对象,只在web环境有效。

    • session:每次会话创建一个对象,只在web环境有效。

    • gloabal-session:一次集群环境的会话创建一个对象,只在web环境有效。

    实时效果反馈

    1. Spring配置文件中,<bean>中的scope属性值为表示该对象是单例的

    A singleton

    B prototype

    C request

    D session

    2. Spring单例对象设置lazy-init=\”false\”表示它的创建时机为

    A 第一次使用对象时创建

    B 每次从容器中获取时都会创建

    C 在容器启动时会创建

    D 每次请求时创建

    答案

    1=>A 2=>C

    IOC_对象的销毁时机

    image-20211126171718292

    对象的创建策略不同,销毁时机也不同:

    • singleton:对象随着容器的销毁而销毁。
    • prototype:使用JAVA垃圾回收机制销毁对象。
    • request:当处理请求结束,bean实例将被销毁。
    • session:当HTTP Session最终被废弃的时候,bean也会被销毁掉。
    • gloabal-session:集群环境下的session销毁,bean实例也将被销毁。

    实时学习反馈

    1. 在Spring中,单例对象销毁

    A 在服务器关闭时

    B 使用JAVA垃圾回收机制

    C 在请求结束时

    D 容器销毁时

    2. 在Spring中,多例对象销毁

    A 在服务器关闭时

    B 使用JAVA垃圾回收机制

    C 在请求结束时

    D 容器销毁时

    答案

    1=>D 2=>B

    IOC_对象的生命周期

    image-20211126174228461

    Bean对象的生命周期包含创建——使用——销毁,Spring可以配置Bean对象在创建和销毁时自动执行的方法:

  • 定义生命周期方法

    public class StudentDaoImpl2 implements StudentDao{
    // 创建时自动执行的方法
    public void init(){
    System.out.println(\”创建StudentDao!!!\”);
    }

    // 销毁时自动执行的方法
    public void destory(){
    System.out.println(\”销毁StudentDao!!!\”);
    }
    }

  • 配置生命周期方法

    <!– init-method:创建对象时执行的方法 destroy-method:销毁对象时执行的方法 –>
    <bean id=\”studentDao\” class=\”com.itbaizhan.dao.StudentDaoImpl2\” scope=\”singleton\”
    init-method=\”init\” destroy-method=\”destory\”></bean>

  • 测试

    @Test
    public void t3(){
    // 创建Spring容器
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(\”bean1.xml\”);

    // 销毁Spring容器,ClassPathXmlApplicationContext才有销毁容器的方法
    ac.close();
    }

  • 实时效果反馈

    1. 在Spring中,<bean>中配置属性可以定义创建对象时执行的方法

    A id

    B method

    C init-method

    D destroy-method

    2. 在Spring中,<bean>中配置属性可以定义销毁对象时执行的方法

    A id

    B method

    C init-method

    D destroy-method

    答案

    1=>C 2=>D

    IOC_获取对象的方式

    image-20211126174452548

    Spring有多种获取容器中对象的方式:

    通过id/name获取

  • 配置文件

    <
    bean
    name=
    \”studentDao\”
    class=
    \”com.itbaizhan.dao.StudentDaoImpl2\”
    ></
    bean
    >

    <
    bean
    id=
    \”studentDao\”
    class=
    \”com.itbaizhan.dao.StudentDaoImpl2\”
    ></
    bean
    >

  • 获取对象

    StudentDao
    studentDao
    = (
    StudentDao)
    ac.
    getBean(
    \”studentDao\”);

  • 通过类型获取

  • 配置文件

  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » Spring(全网最详细)值得收藏
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!