深入浅出讲解Spring框架中依赖注入与控制反转及应用

深入浅出讲解Spring框架中依赖注入与控制反转及应用

什么是依赖注入和控制反转

在传统的 Java 应用中,在一个类中如果需要依赖另一个类的对象,我们通常会使用“new”关键字手动创建这个对象。例如:

public class UserService {

    private UserDao userDao = new UserDao();

    // 其他方法
    // ...
}

这种方式虽然简单,但是有一个缺点,就是这样耦合度高、扩展性差。例如如果 UserDao 的实现类需要变更,我们需要在所有依赖 UserDao 的业务类中修改代码。而且对于不同的环境,我们还需要手动修改代码。

此时依赖注入和控制反转就要登场了。

  • 依赖注入(Dependency Injection)是指,通过引入 IoC 容器,在容器中动态加载对象,并将这些对象注入到需要使用它们的类中,从而实现对象与对象之间的解耦。
  • 控制反转(Inversion of Control,IoC)是指,将对象的控制权由程序员转移到框架中,由框架帮我们管理对象的声明周期和依赖关系,从而实现程序的解耦。

Spring 中的依赖注入和控制反转

在 Spring 中,我们使用 BeanFactory 或者 ApplicationContext 容器来管理对象,并使用依赖注入来解决对象之间的依赖关系。

BeanFactory

在 Spring 中,BeanFactory 是一个很基础的容器,可以创建和管理对象。下面是一个示例:

<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

<bean id="userService" class="com.example.service.UserService">
    <property name="userDao" ref="userDao"/>
</bean>

在这个示例中,我们创建了一个 UserDao 对象,并将其注入到 UserService 中。UserService 中的 userDao 属性使用 “property” 元素来注入,其中 “name” 表示属性名,ref=”userDao” 表示注入 userDao bean。

ApplicationContext

ApplicationContext 是一个更高级的容器,除了 BeanFactory 的所有功能外,还提供了更加方便的集成功能,例如国际化、事件处理、资源加载等。下面是一个示例:

<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

<bean id="userService" class="com.example.service.UserService"/>

在这个示例中,我们创建了一个 UserDao 对象,和一个 UserService 对象。注意,这里并没有显式地指定 UserDao 对象的注入方式,Spring 会自动检测 UserService 中的需要注入的属性,并自动注入相应的对象。

示例1:构建一个基础的 Spring 应用

接下来,我们将演示如何使用 Spring 的依赖注入和控制反转功能,构建一个简单的 Spring 应用程序。

步骤

首先,创建一个基础的 Spring 应用程序,包含以下文件和类:

  1. pom.xml:用于管理项目依赖。
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.9.RELEASE</version>
    </dependency>
</dependencies>
  1. UserDao.java:创建一个 UserDao 接口。
public interface UserDao {
    void save();
}
  1. UserDaoImpl.java:创建 UserDao 的实现类。
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("UserDaoImpl save method called");
    }
}
  1. UserService.java:创建 UserService 接口。
public interface UserService {
    void register();
}
  1. UserServiceImpl.java:创建 UserService 的实现类,并在其属性中注入 UserDao。
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void register() {
        userDao.save();
        System.out.println("UserServiceImpl register method called");
    }
}
  1. applicationContext.xml:配置 Spring 容器。
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

<bean id="userService" class="com.example.service.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>
  1. Main.java:创建主函数用于测试应用程序。
public class Main {
    public static void main(String[] args) {
        // 加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取 UserService 实例
        UserService userService = context.getBean(UserService.class);
        // 调用 register 方法
        userService.register();
        // 关闭 Spring 容器
        context.close();
    }
}

实现过程

  1. 在 UserDao.java 中,我们创建了 UserDao 接口,其中定义了一个 save() 方法。

  2. 在 UserDaoImpl.java 中,我们创建了 UserDao 的实现类,并实现了 save() 方法。这个方法只是简单的打印一条消息,表示方法被调用了。

  3. 在 UserService.java 中,我们创建了 UserService 接口,并定义了一个 register() 方法。

  4. 在 UserServiceImpl.java 中,我们创建了 UserService 的实现类,并在其属性 userDao 中注入 UserDao 对象。在 register() 方法中,我们调用了 userDao 的 save() 方法,并打印了一条消息表示方法被调用了。

  5. 在 applicationContext.xml 中,我们配置了 Spring 容器,一共定义了两个 bean:userDao 和 userService。userService 中的 userDao 属性通过注入方式来实现。

  6. 在 Main.java 中,我们创建了主函数用于测试应用程序。我们加载了 applicationContext.xml 配置文件,并通过 context.getBean() 方法获取 UserService 实例。最后,调用 register() 方法,并关闭 Spring 容器。

到此为止,我们就完成了一个使用 Spring 的依赖注入和控制反转功能的简单应用程序。在运行程序时,我们可以看到控制台输出:

UserDaoImpl save method called
UserServiceImpl register method called

示例2:在 Spring Boot 应用程序中使用依赖注入

在 Spring Boot 应用程序中,Spring 自动配置了很多对象来简化我们的开发,我们只需要添加相关依赖,并在代码中注入相应的对象即可。

在这个示例中,我们将演示如何在 Spring Boot 应用程序中使用依赖注入。

步骤

首先,创建一个 Spring Boot 应用程序,包含以下文件和类:

  1. pom.xml:用于管理项目依赖。
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.4.RELEASE</version>
        <scope>test</scope>
    </dependency>
</dependencies>
  1. UserDao.java:创建一个 UserDao 接口。
public interface UserDao {
    void save();
}
  1. UserDaoImpl.java:创建 UserDao 的实现类。
@Repository
public class UserDaoImpl implements UserDao {

    public void save() {
        System.out.println("UserDaoImpl save method called");
    }
}
  1. UserService.java:创建 UserService 接口。
public interface UserService {
    void register();
}
  1. UserServiceImpl.java:创建 UserService 的实现类,并使用 @Autowired 注解对 UserDao 进行注入。
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public void register() {
        userDao.save();
        System.out.println("UserServiceImpl register method called");
    }
}
  1. Main.java:创建主函数用于测试应用程序。
@RestController
public class Main {

    @Autowired
    UserService userService;

    @RequestMapping("/register")
    public String register() {
        userService.register();
        return "success";
    }

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

实现过程

  1. 在 UserDao.java 中,我们创建了 UserDao 接口,其中定义了一个 save() 方法。

  2. 在 UserDaoImpl.java 中,我们创建了 UserDao 的实现类,并使用 @Repository 注解将它声明为一个 bean。这个类中也实现了 save() 方法。

  3. 在 UserService.java 中,我们创建了 UserService 接口,并定义了一个 register() 方法。

  4. 在 UserServiceImpl.java 中,我们创建了 UserService 的实现类。这个类中使用 @Service 注解将其声明为一个 bean,并在 userDao 属性上使用 @Autowired 注解来进行注入。在 register() 方法中,我们调用了 userDao 的 save() 方法,并打印了一条消息表示方法被调用了。

  5. 在 Main.java 中,我们创建了主函数,并使用 @RestController 注解将其声明为一个 web 服务。在这个类中,我们将 UserService 注入到 userService 属性中,并编写了一个 /register 的接口用于测试服务。这个接口调用了 userService 的 register() 方法。

通过运行应用程序,我们可以在控制台上看到应用已经启动了。打开浏览器,输入 http://localhost:8080/register ,我们可以看到该接口调用了 UserServiceImpl 中的 register() 方法,并打印了一条消息表示方法被调用了。

至此,我们已经完成了如何在 Spring 应用程序和 Spring Boot 应用程序中使用依赖注入和控制反转的介绍。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入浅出讲解Spring框架中依赖注入与控制反转及应用 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • @RequestBody注解Ajax post json List集合数据请求400/415的处理

    首先介绍一下问题的背景,前端使用Ajax技术向后端发送一个POST请求,请求的数据是JSON格式的List集合数据,后端使用Spring MVC框架,利用注解@RequestBody将这个JSON数据映射到后端的Java对象中。但是在处理过程中,出现了400或者415的错误码,这是因为后端无法正确解析请求的JSON数据。那么如何处理这个问题呢?接下来我们来一…

    Java 2023年5月26日
    00
  • Java流形式返回前端的实现示例

    针对Java流形式返回前端的实现示例,一般可以通过以下步骤实现: 1. 定义实体类 首先需要定义一个实体类,用来封装需要返回给前端的数据,包括需要返回的字段及其数据类型,例如: public class User { private int id; private String name; private int age; //构造函数、getter和set…

    Java 2023年5月27日
    00
  • java中的转义字符介绍

    那么我们来详细讲解一下“Java中的转义字符介绍”。 什么是转义字符? 在 Java 中,有一些字符是有特殊意义的,如换行符、制表符等,如果需要在字符串中使用这些特殊字符时,我们需要使用转义字符来表示这些特殊字符。转义字符是以反斜杠(\)开头的字符组合,用于表示一些特殊字符和控制字符。下面是一些常用的转义字符列表: 转义字符 含义 \n 换行符 \r 回车符…

    Java 2023年5月27日
    00
  • Spring整合MyBatis(Maven+MySQL)图文教程详解

    下面我就详细讲解一下 “Spring整合MyBatis(Maven+MySQL)图文教程详解” 的完整攻略。 概述 在 “Spring整合MyBatis(Maven+MySQL)图文教程详解” 中,我们将会使用 Maven 构建一个 Web 应用程序,并使用 Spring 和 MyBatis 框架来实现数据持久化。 该教程主要包括以下步骤: 创建 Maven…

    Java 2023年5月19日
    00
  • intellij idea的快速配置使用详细教程

    Intellij IDEA的快速配置使用详细教程 简介 Intellij IDEA 是一个流行的 Java 集成开发环境,具有高效可扩展、强大且智能的代码编辑器和丰富的工具集。下面是 Intellij IDEA 的快速配置使用详细教程。 步骤 下载和安装在官网 https://www.jetbrains.com/idea/ 上下载适合你的操作系统版本并安装。…

    Java 2023年5月20日
    00
  • JavaWeb实现文件上传功能详解

    JavaWeb实现文件上传功能详解 1. 介绍 文件上传是Web应用中常用的一种功能,例如用户上传头像或者附件。本文将介绍JavaWeb中文件上传的实现方式。 2. 实现方式 2.1 方式一:使用第三方库commons-fileupload 添加依赖 在Maven中使用以下依赖添加commons-fileupload: <dependency> …

    Java 2023年5月19日
    00
  • Spring AOP切面解决数据库读写分离实例详解

    下面是完整的攻略: 简介 在基于Spring框架进行开发时,为了提高数据库的读写性能,可以将读写操作分别分配到不同的数据库中,这就是数据库读写分离。Spring框架提供了AOP编程,可以把业务逻辑和数据库操作分开,使得业务逻辑更加专注,减少代码的耦合度。本文基于Spring AOP切面,详细演示实现数据库读写分离的过程。 准备工作 一、配置依赖 在pom.x…

    Java 2023年6月15日
    00
  • Java手写线程池的实现方法

    下面我将详细讲解Java手写线程池的实现方法的完整攻略。在此过程中,我将会介绍线程池的概念和原理,并提供两个示例来帮助理解。 一、线程池的概念 线程池是一种多线程处理的方式,它可以让线程进行复用,避免频繁创建和销毁线程带来的开销。线程池一般由三部分组成:任务队列、工作线程和线程管理器。 二、线程池的实现方法 1. 创建任务类 任务类用于封装具体的任务逻辑,需…

    Java 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部