Spring DI 笔记

发布于:2024-10-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

1.什么是DI?

 2.依赖注入的三种⽅式

2.1属性注⼊ 

2.2构造⽅法注⼊

 2.3Setter 注⼊

 2.4三种注⼊优缺点分析

3.@Autowired存在问题 


1.什么是DI?

DI: 依赖注⼊
依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象

简单来说, 就是把对象取出来放到某个类的属性中.

关于依赖注⼊, Spring也给我们提供了三种⽅式:

1.属性注⼊(Field Injection)

2.构造⽅法注⼊(Constructor Injection)

3.Setter 注⼊(Setter Injection)

都是使用@Autowired实现的。 

接下来,我们分别来看.


 2.依赖注入的三种⽅式

都是使用@Autowired实现的 

我们接下来会频繁使用到UserService类和UserController类以及获取 UserController 中的 sayHi⽅法。

1.UserService代码:

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void doService(){
        System.out.println("doService~~~~");
    }
}

 2.UserController类依照我们选择的注入⽅式决定。

3.获取 UserController 中的 sayHi⽅法:

​
import com.wh.ioc.Controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

//@ComponentScan(basePackages = "~~~~~")
@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);

        UserController bean = context.getBean(UserController.class);
        bean.sayHi();
    }
}

​

2.1属性注⼊ 

UserController类的实现代码如下:

import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

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

    public void sayHi(){
        userService.doService();
        System.out.println("UserController Hi");
    }
}

2.2构造⽅法注⼊

import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    private UserService userService;

    public UserController() {
    }
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        userService.doService();
        System.out.println("UserController Hi");
    }
}

注意:

  如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法,
那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法。

 补充:

关于构造函数规范:

1.当我们添加有参构造函数时,一定也要把无参构造函数也添加上。

2.依赖注入时,就算只有一个构造函数也要添加@Autowired注解

 2.3Setter 注⼊

注解一定不能少

import com.wh.ioc.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    private UserService userService;


    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        userService.doService();
        System.out.println("UserController Hi");
    }
}

 2.4三种注⼊优缺点分析

1.属性注⼊

优点:

简洁,使⽤⽅便

缺点:

(1) 只能⽤于 IoC 容器 ,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指 针异常)
(2) 不能注⼊⼀个Final修饰的属性

 2.构造函数注⼊(Spring 4.X推荐)

 优点:

(1)注⼊的对象不会被修改

(2)可以注⼊final修饰的属性

(3)依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法

(4)通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

缺点:

注⼊多个对象时, 代码会⽐较繁琐 

3.Setter注⼊(Spring 3.X推荐)  

优点:
⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊

缺点:

1.不能注⼊⼀个Final修饰的属性

2.注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险 


3.@Autowired存在问题 

我们接下来用打印学生信息的例子来说明

Student类:

import lombok.Data;

@Data
public class Student {
    private String name;
    private Integer id;

    public Student() {

    }

    public Student(String name) {
        this.name = name;
    }

    public Student(String name, Integer id) {
        this.name = name;
        this.id = id;
    }
}
BeanConfig类:
import com.wh.ioc.Model.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {

    @Bean
    public Student StudentInfo() {
        return new Student("wh",01);
    }
    @Bean
    public Student StudentInfo2() {
        return new Student("Bob",02);
    }
}
DomeController类:
import com.wh.ioc.Model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class DomeController {
    @Autowired
    private Student student;
    public void say(){
        System.out.println(student);
    }
}

启动类:

import com.wh.ioc.Controller.DomeController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

//@ComponentScan(basePackages = "~~~~~")
@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);

        DomeController bean = context.getBean(DomeController.class);
        bean.say();
    }
}

运行:

报错的原因是,⾮唯⼀的 Bean 对象 

解释:

@Autowired是先按照类型去注入,匹配到多个对象时,再按照名称去注入。

如果我们明确注入对象的名称,则可以正确打印该学生信息。

DomeController类代码:

import com.wh.ioc.Model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class DomeController {
    @Autowired
    private Student StudentInfo2;
    public void say(){
        System.out.println(StudentInfo2);
    }
}

结果:

 

那当我们没有明确注入对象的名称,又想得到正确结果我们可以怎么做?

有以下⼏种解决⽅案:
1.@Primary
2.@Qualifier
3.@Resource

1. @Primary

使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现。

直接加到Bean注⼊的方法上。

@Primary
@Bean
public Student StudentInfo() {
    return new Student("wh", 01);
}

2.@Qualifier

使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean 的名称。
@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
@Controller
public class DomeController {
    @Qualifier("StudentInfo2")
    @Autowired
    private Student student;
    public void say(){
        System.out.println(student);
    }
}

3.@Resource注解

本身就是依赖注入注解,是按照bean的名称进⾏注⼊

@Controller
public class DomeController {
    @Resource(name = "StudentInfo")
    private Student student;
    public void say(){
        System.out.println(student);
    }
}

@Autowird 与 @Resource的区别是?

 1.@Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解

 2.@Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊. 相⽐于 @Autowired 来说, @Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean


以上为我个人的小分享,如有问题,欢迎讨论!!! 

都看到这了,不如关注一下,给个免费的赞