Spring 依赖注入

目录

2.更加简单的获取 Bean

2.1 属性注入

2.1.1 属性注入优点

2.1.2 属性注入缺点

2.2 Setter 注入

2.2.1 优点

2.2.2 缺点

2.3 构造方法注入

2.3.1 优点

2.3.2 缺点

2.4 @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 类的实现代码如下:

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 类的实现代码如下:

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

}

获取 UserService 中的 getUser ⽅法:

class UserServiceTest {

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

2️⃣获取多个对象:

User 类的实现代码如下:

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当中:

@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 (根据名称)进行匹配

@Service
public class UserService2 {
    //属性注入
    @Autowired
    private User user;

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

生成 UserService2Test 单元测试:

class UserService2Test {

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

Spring 依赖注入_第1张图片

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

执行 测试类:

Spring 依赖注入_第2张图片

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

解决方案:

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

Spring 依赖注入_第3张图片

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

Spring 依赖注入_第4张图片

3️⃣使用 @Resource

Spring 依赖注入_第5张图片

2.1.1 属性注入优点

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

2.1.2 属性注入缺点

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

Spring 依赖注入_第6张图片

final 特征

  • 被 final 修饰的变量需要直接赋值

  • 在构造方法中进行赋值

Spring 依赖注入_第7张图片

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

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

2.2 Setter 注入

//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 本来就是一个方法,有可能被多次调用和修改)

Spring 依赖注入_第8张图片

2.3 构造方法注入

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

@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 进行注入

Spring 依赖注入_第9张图片

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:


    
        org.springframework
        spring-beans
        5.2.3.RELEASE
    
    
        org.springframework
        spring-context
        5.2.3.RELEASE
    

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



    

新建目录 spring.java.demo:

Spring 依赖注入_第10张图片

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

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 类:

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

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

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

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

新建 controller.UserController 类:

@Controller
public class UserController {
    @Autowired
    private UserService userService;

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

全局类(启动类)User:

/**
 * 启动类
 */
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());
    }
}

你可能感兴趣的:(Spring,spring,java,后端)