Spring 依赖注入

目录

[2.更加简单的获取 Bean](#2.更加简单的获取 Bean)

[2.1 属性注入](#2.1 属性注入)

[2.1.1 属性注入优点](#2.1.1 属性注入优点)

[2.1.2 属性注入缺点](#2.1.2 属性注入缺点)

[2.2 Setter 注入](#2.2 Setter 注入)

[2.2.1 优点](#2.2.1 优点)

[2.2.2 缺点](#2.2.2 缺点)

[2.3 构造方法注入](#2.3 构造方法注入)

[2.3.1 优点](#2.3.1 优点)

[2.3.2 缺点](#2.3.2 缺点)

[2.4 @Resource:另⼀种注入关键字](#2.4 @Resource:另⼀种注入关键字)

[2.4.1 @Autowired VS @Resource 区别](#2.4.1 @Autowired VS @Resource 区别)

3.专项训练


2.更加简单的获取 Bean

获取 Bean 对象也叫做 对象装配 ,是把对象取出来放在某个类中,有时候也叫 对象注入

对象装配(对象注入)的实现3种方式:

1️⃣属性注入

2️⃣构造方法注入

3️⃣Setter 注入

2.1 属性注入

使用 @Autowired 实现:首先先根据 getTyoe (从容器中)获取对象,如果只获取一个,那么直接将此对象注入到当前属性上;如果获取多个对象,才会使用 getName (根据名称)进行匹配

1️⃣例如,将 UserRepository 类注入到 UserService 类中:

UserService 类的实现代码如下:

java 复制代码
package com.java.demo.service;

import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WJZ
 * Date: 2023-10-16
 * Time: 11:33
 */
@Service
public class UserService {

    //1.属性注解
    @Autowired  //DI(依赖注入)
    private UserRepository userRepository;//从spring当中取到UserRepository,并把它设值给当前变量

    public int add() {
        System.out.println("Do UserService add method");

        //传统写法
        //UserRepository userRepository = new UserRepository();
        //return userRepository.add();

        //spring V1.0
        /*ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
        return userRepository.add();*/

        //spring V2.0
        return userRepository.add();


    }
}

UserRepository 类的实现代码如下:

java 复制代码
@Repository
public class UserRepository {
    public int add() {
        System.out.println("Do UserRepository add method ");
        return 1;
    }

}

获取 UserService 中的 getUser ⽅法:

java 复制代码
class UserServiceTest {

    @Test
    void add() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

2️⃣获取多个对象:

User 类的实现代码如下:

java 复制代码
public class User {
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

将 User 对象存储到 Spring当中:

java 复制代码
@Component
public class Users {
    @Bean("user1")
    public User user1() {
        User user = new User();
        user.setName("张三");
        return user;
    }
    @Bean("user2")
    public User user2() {
        User user = new User();
        user.setName("李四");
        return user;
    }
}

在 UserService2 中调用 User 对象(这个对象相同类型存储到 spring 中有两个,则根据 getName (根据名称)进行匹配

java 复制代码
@Service
public class UserService2 {
    //属性注入
    @Autowired
    private User user;

    public void sayHi() {
        System.out.println(user.toString());
    }
}

生成 UserService2Test 单元测试:

java 复制代码
class UserService2Test {

    @Test
    void sayHi() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserService2 userService2 = context.getBean("userService2", UserService2.class);
        userService2.sayHi();
    }
}

上述代码含义:在 @Autowired 中注入 User 对象:User对象放在 Users 当中,Users 存放在 demo 包下,会随着 spring 启动而启动,也就是说 spring 启动的时候,就会在 spring 框架中存 user1 = 张三 和use2 = 李四 (类型都是 User),通过单元测试拿到 UserService2,在UserService2 中注入 User 对象,打印信息

执行 测试类:

获取报错:获取唯一一个bean,但是找到了两个 bean

解决方案:

1️⃣将属性的名字和 Bean 的名字对应上

2️⃣使用 @Autowired 配合 @Qualifier 一起使用

3️⃣使用 @Resource

2.1.1 属性注入优点

属性注入最大的优点就是实现简单、使用简单,只需要给变量上添加一个注解(@Autowired),就可以在不 new 对象的情况下,直接获得注入的对象了(这就是 DI 的功能和魅力所在),所以它的优点就是使用简单。

2.1.2 属性注入缺点

1️⃣无法注入 final 修饰的变量

final 特征

  • 被 final 修饰的变量需要直接赋值
  • 在构造方法中进行赋值

2️⃣通用性问题:只适用于 IoC 容器

3️⃣更容易违背单一设计原则,因为使用起来比较简单

2.2 Setter 注入

java 复制代码
//Setter 注入
@Service
public class UserService3 {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void sayHi() {
        System.out.println("Do UserService3 sayHi method");
        userRepository.add();
    }
}

2.2.1 优点

通常 Setter 只 Set 一个书属性,所以 Setter 注入更符合单一设计原则

2.2.2 缺点

1️⃣无法注入 final 修饰的变量

2️⃣setter 注入的对象可以被修改(setter 本来就是一个方法,有可能被多次调用和修改)

2.3 构造方法注入

造方法注入是 Spring 官方从 4.x 之后推荐的注入方式

java 复制代码
@Service
public class UserService4 {
    private UserRepository userRepository;

    @Autowired
    public UserService4(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void sayHi() {
        System.out.println("Do UserService4 sayHi");
        userRepository.add();
    }
}

如果当前的类中只有一个构造方法,那么 @Autowired 也可以省略

2.3.1 优点

1️⃣可以注入 final 修饰的变量

2️⃣注入的对象是不会被修改(因为构造方法只会加载一次)

3️⃣构造方法注入可以保证注入对象完全初始化

4️⃣构造方法注入通用性更好

2.3.2 缺点

1️⃣写法比属性注入复杂

2️⃣使用构造方法注入,无法解决循环依赖的问题

2.4 @Resource:另⼀种注入关键字

在进⾏类注入时,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入

2.4.1 @Autowired VS @Resource 区别

1️⃣出身不同:@Resource 来自于JDK;@Autowired 来自于 Spring 框架

2️⃣支持的参数不同:@Resource 支持很多参数设;@Autowired 只支持一个参数设置(@Qualifier)

3️⃣使用区别:@Resource 不支持构造方法注入;而 @Autowired 支持构造方法注入

4️⃣idea 兼容性支持不同:使用 @Autowired 在 idea 专业版可能会报错;@Resource 不存在误报的问题

@Autowired来自于 spring,spring 框架是在程序执行之后再执行,不能检测到当前类是否注入(注入是的到 spring 当中)

@Resource:java代码是在程序执行之前执行的,能检测到已经注入

例如:我在开直播,有人先进来可以听到我之前讲的知识,有人后来就听不到我之前讲的知识,但是对于这个知识我已经讲过了,这个知识点是存在的。

3.专项训练

在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤ Service 类,Service 再通过注⼊的⽅式获取到 Repository 类, 类⾥⾯有⼀个⽅法构建⼀个 User 对象,返回给 main ⽅法。Repository ⽆需连接数据库,使⽤伪代码即

创建 Maven项目,添加依赖pom.xml:

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
</dependencies>

新建 spring 配置文件spring-config.xml:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="spring.java.demo"></content:component-scan>
</beans>

新建目录 spring.java.demo:

在新建 repository.UserRepository 类之前需要有一个 User 对象,新建 model.User 类:

java 复制代码
public class User {
    private int id;
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

新建 repository.UserRepository 类:

java 复制代码
@Repository
public class UserRepository {
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

新建 service.UserService 类(只是业务组装):

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

    public User getUser() {
        return userRepository.getUser();
    }
}

新建 controller.UserController 类:

java 复制代码
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    public User getUser() {
        return userService.getUser();
    }
}

全局类(启动类)User:

java 复制代码
/**
 * 启动类
 */
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController = context.getBean("userController", UserController.class);
        System.out.println(userController.getUser());
    }
}
相关推荐
代码小鑫3 分钟前
A031-基于SpringBoot的健身房管理系统设计与实现
java·开发语言·数据库·spring boot·后端
Json____8 分钟前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库
monkey_meng28 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss36 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
我救我自己36 分钟前
UE5运行时创建slate窗口
java·服务器·ue5
2401_853275731 小时前
ArrayList 源码分析
java·开发语言
爪哇学长1 小时前
SQL 注入详解:原理、危害与防范措施
xml·java·数据库·sql·oracle
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
她说彩礼65万1 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc
MoFe11 小时前
【.net core】【sqlsugar】字符串拼接+内容去重
java·开发语言·.netcore