Spring IoC&DI(3)

DI详解

接下来学习一下依赖注入DI的细节.

依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了@Autowired这个注解, 完成了依赖注入这个操作.

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

在一些文章中, 依赖注入也称为"对象注入", "属性装配", 具体含义需要结合文章的上下文理解.

关于依赖注入, Spring提供了三种方式:

1.属性注入(Field Injection)

2.构造方法注入(Constructor Injection)

3.Setter注入(Setter Injection).

属性注入

属性注入通过@Autowired实现的, 这里将Service类注入到Controller类中.

@Service
public class MyService {
    public void sayHi() {
        System.out.println("Hi, MyService");
    }
}
@Controller //将对象存储到Spring中
public class MyController2 {
    //注入方法1: 属性注入
    @Autowired 
    private MyService myService;

    public void sayHi() {
        System.out.println("Hi, UserController...");
        myService.sayHi();
    }
}

使用:

@SpringBootApplication
public class SpringbootDemoApplication {
	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(SpringbootDemoApplication.class);
		MyController2 myController = context.getBean(MyController2.class);
		myController.sayHi();
	}
}

最终运行结果如下:

 

构造方法注入

构造方法注入是在类的构造方法中实现注入, 如下所示:

@Controller //将对象存储到Spring中
public class MyController2 {
    private MyService myService;

    //注入方法2: 构造方法注入
    @Autowired
    public MyController2(MyService myService) {
        this.myService = myService;
    }

    public void sayHi() {
        System.out.println("Hi, UserController...");
        myService.sayHi();
    }
}

注意事项: 如果类中只有一个构造方法, 那么@Autowired注解可以省略(在Spring中, 如果一个类只有一个构造方法, 并且该构造方法不包含任何参数, 那么Spring在实例化这个类的时候会自动将其作为一个Bean注入到容器中); 如果类中有多个构造方法, 那么需要添加上@Autowired来明确指明到底使用哪个构造方法

Setter注入

Setter注入和属性的Setter方法实现类似, 只不过在设置set方法的时候需要加上@Autowired注解:

@Controller //将对象存储到Spring中
public class MyController2 {
    private MyService myService;

    //注入方法3: Setter方法注入
    @Autowired
    public void setMyService(MyService myService) {
        this.myService = myService;
    }

    public void sayHi() {
        System.out.println("Hi, UserController...");
        myService.sayHi();
    }
}

 这里注意, 对于Setter方法, 是一定要写@Autowired的.

@Autowired存在问题

当同一类型存在多个bean时, 使用@Autowired会存在问题.

@Component
public class BeanConfig {
    @Bean("u1")
    public User user1() {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}
@Controller
public class MyController4 {
    @Autowired
    private User user;

    public void sayHi() {
        System.out.println("hi, UserController4...");
        System.out.println(user);
    }
}

运行结果:

报错的原因是, 非唯一的Bean对象.

如何解决上述问题呢? Spring提供了以下几种解决方案:

@Primary

@Qualifier

@Resource 

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

@Component
public class BeanConfig {
    @Primary // 指定该bean为默认的bean实现.
    @Bean("u1")
    public User user1() {
        User user = new User();
        user.setName("lisi");
        user.setAge(20);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

使用@Qualifier注解: 指定要注入的bean对象. 在@Qualifier的value属性中,指定注入bean的名称.

@Qualifier注解不能单独使用, 必须配合@Autowired使用.

@Controller
public class MyController4 {
    @Qualifier("user2") //指定bean的名称.
    @Autowired
    private User user;

    public void sayHi() {
        System.out.println("hi, UserController4...");
        System.out.println(user);
    }
}

使用@Resource注解: 是按照bean的方式注入. 通过name属性指定要注入的bean名称. 

@Controller
public class MyController4 {
    @Resource(name = "user2")
    private User user;

    public void sayHi() {
        System.out.println("hi, UserController4...");
        System.out.println(user);
    }
}

常见面试题:

@Autowired和@Resource的区别

@Autowired是Spring框架提供的注解, 而@Resource是JDK提供的注解.(@Primary, @Qualifier是Spring提供的注解).

@Autowired默认是按照类型注入, 而@Resource是按名称注入. 相比于@Autowired来说, @Resource支持更多的参数配置, 例如name设置, 通过name获取bean. 

相关推荐

  1. 3.11笔记3

    2024-03-31 15:20:08       39 阅读
  2. 3.3 语法规则

    2024-03-31 15:20:08       46 阅读
  3. <span style='color:red;'>3</span>-Mybatis

    3-Mybatis

    2024-03-31 15:20:08      60 阅读
  4. vue 3

    2024-03-31 15:20:08       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-31 15:20:08       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-31 15:20:08       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-31 15:20:08       87 阅读
  4. Python语言-面向对象

    2024-03-31 15:20:08       96 阅读

热门阅读

  1. PowerShell数组

    2024-03-31 15:20:08       37 阅读
  2. Log4j远程代码执行

    2024-03-31 15:20:08       30 阅读
  3. Redisson兼容redis多模式部署的配置方式

    2024-03-31 15:20:08       38 阅读
  4. 【微服务篇】深入理解分布式消息队列系统

    2024-03-31 15:20:08       38 阅读
  5. mybatis EXISTS

    2024-03-31 15:20:08       32 阅读
  6. 深入理解zookeeper

    2024-03-31 15:20:08       40 阅读
  7. git 基于当前分支创建新分支

    2024-03-31 15:20:08       36 阅读
  8. sql-学习-day1

    2024-03-31 15:20:08       38 阅读
  9. Flutter开发的Web应用 构建及部署 标准流程指南

    2024-03-31 15:20:08       31 阅读
  10. Github 2024-03-27C开源项目日报Top10

    2024-03-31 15:20:08       36 阅读
  11. go 安装

    2024-03-31 15:20:08       35 阅读
  12. LeetCode热题Hot100 - 寻找两个正序数组的中位数

    2024-03-31 15:20:08       40 阅读
  13. Go-JWT完整示例

    2024-03-31 15:20:08       40 阅读
  14. c语音函数大全(V开头)

    2024-03-31 15:20:08       36 阅读