初识Spring

Spring主要的内容是IoC(控制反转)和DI(依赖注入)。

1.为什么要IoC?

控制反转是一种设计原则,它将对象的创建、管理和依赖关系的处理从应用程序代码中转移到外部容器中。简单来说,它通过将对象的控制权从程序代码反转到外部框架或容器来实现。

传统的控制流

在传统的编程模型中,对象的创建和管理是由应用程序代码直接控制的。例如:

java 复制代码
public class UserService {
    private UserRepository userRepository;

    public UserService() {
        this.userRepository = new UserRepository();
    }

    public void saveUser(User user) {
        userRepository.save(user);
    }
}

在这个例子中,UserService 类直接创建了一个 UserRepository 对象(通过new)。这意味着 UserService 依赖于 UserRepository,并且 UserService 控制了 UserRepository 的生命周期。

控制反转的实现

在控制反转的情况下,对象的创建和依赖关系的管理由一个框架或容器来处理。例如,在一个依赖注入(Dependency Injection, DI)框架中,通常会有一个配置文件或注解来描述对象之间的关系,框架会自动创建这些对象并注入它们所需的依赖。

java 复制代码
public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void saveUser(User user) {
        userRepository.save(user);
    }
}

在这个例子中,UserRepository 对象不再是 UserService 直接创建的,而是通过构造函数注入的。这意味着 UserService 不再控制 UserRepository 的创建和管理,而是由外部的 IoC 容器来负责。

为什么要控制反转?

  1. 解耦:通过将对象的创建和管理从应用程序代码中分离出来,可以减少代码之间的耦合度。这样,当你需要更改某个类的实现时,不必修改依赖它的所有类。

  2. 可测试性:控制反转使得单元测试更加容易。你可以轻松地使用模拟对象(Mock Object)来替换实际的依赖对象,从而隔离测试目标。

  3. 灵活性:通过配置方式来管理对象的依赖关系,可以更容易地进行系统配置和调整。例如,你可以在不改变代码的情况下,通过配置文件或注解来切换不同的实现类。

  4. 代码复用:控制反转通常伴随着面向接口编程,这使得代码更加通用和可复用。你可以编写更抽象的代码,依赖于接口而不是具体的实现。

  5. 可维护性:由于对象的创建和管理被集中处理,代码的可维护性得到了提高。开发者可以更专注于业务逻辑,而不必担心对象的生命周期和依赖管理

总结

用白话来说,就是我们在创建对象的时候,不希望自己手动new一个,这就需要将这个过程交给别人完成,而这个人,就是IoC容器。

如上图所示,我们把创建对象的工作交给IoC,这样,当我们需要一个对象来调用方法时,我们只需要"声明"这个对象即可。而且,当Service需要依赖于Dao时,也不需要我们自己手动设置关系,可以交由IoC完成。

2.创建Spring工程

2.1导入依赖

首先4个依赖,注意以后每次使用Spring框架都要引入这四个依赖:

XML 复制代码
<dependencies>
     <!--        4个核心配置-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.1.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>6.1.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.1.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>6.1.10</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

2.2配置bean

在resources文件夹下创建"applicationContext.xml"文件,具体内容如下:

XML 复制代码
<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/>


</beans>

接下来我们引入,需要管理的类(这里叫做bean)(一定要注意,不是引入接口,而是类)

<bean> 元素的基本格式

在 Spring 配置文件中,<bean> 元素用于定义一个 Java 对象(即 Bean),并将其交给 Spring IoC 容器管理。<bean> 元素的基本格式如下:

XML 复制代码
<bean id="beanName" class="FullyQualifiedClassName">
    <!-- 其他属性或子元素 -->
</bean>

各个属性的含义

  1. id 属性

    • 用于唯一标识这个 Bean,方便在其他地方引用。
    • 例如:id="bookDao"
  2. class 属性

    • 指定这个 Bean 对应的 Java 类的全限定名(Fully Qualified Class Name)。
    • 例如:class="com.itheima.dao.impl.BookDaoImpl"

获取IoC容器

java 复制代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        // 获取 Spring IoC 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        // 继续操作:获取 Bean
    }
}

获取到 ApplicationContext 后,可以使用 getBean 方法来获取 Bean。getBean 方法有多个重载形式,可以根据 Bean 的 id 或类型来获取 Bean。

java 复制代码
// 根据 Bean 的 id 获取 Bean
BookDao bookDao = (BookDao) context.getBean("bookDao");

假设 BookService 依赖于 BookDao,并且 BookService 的实现类中已经通过构造函数注入了 BookDao,可以这样获取和使用 Bean:

java 复制代码
public class MainApp {
    public static void main(String[] args) {
        // 获取 Spring IoC 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        // 根据 id 获取 BookService Bean
        BookService bookService = (BookService) context.getBean("bookService");
        
        // 使用 BookService 对象
        bookService.saveBook(new Book("Spring in Action"));
    }
}

DI入门

我们可以思考以下几个问题:

1.基于IoC管理bean

2.Service中使用new形式创建Dao对象是否保留?(否)

3.Service中需要的dao对象如何进入到Service中?(提供方法)

4.Service与Dao间的关系如何描述?(配置)

我们的BookServiceImpl类如下:

java 复制代码
public class BookService {
    private BookDao bookDao;
    public void save(){
        System.out.println("book service save...");
    }
    
    //使用setter方法
    public void setBookDao(BookDao bookDao){
        this.bookDao = bookDao;
    }
}

注意到这里我们没有使用new()方法!

下面要配置Bean之间的关系

XML 复制代码
<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <!--配置service与dao之间的关系,注意是service种引用的dao-->
        <property name="bookDao" ref="bookDao"/>
        <!--property标签中name指的是,这个类BookServiceImpl中定义的bookDao的名字-->
        <!--而ref是,在这个xml文件中每个bean的id-->

    </bean>


</beans>
相关推荐
码上一元1 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田1 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
魔道不误砍柴功3 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
失落的香蕉3 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
枫叶_v3 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
wclass-zhengge3 小时前
SpringCloud篇(配置中心 - Nacos)
java·spring·spring cloud
路在脚下@3 小时前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet
黑马师兄3 小时前
SpringBoot
java·spring
数据小小爬虫3 小时前
如何用Java爬虫“偷窥”淘宝商品类目API的返回值
java·爬虫·php
暮春二十四3 小时前
关于用postman调用接口成功但是使用Java代码调用却失败的问题
java·测试工具·postman