Spring IoC和DI

小灰灰 2024-04-25 08:43 160阅读 0赞

目录

IoC是什么?

理解IoC

示例

为什么要使用IOC

DI是什么?

IoC

@Controller(控制器存储)

@Controller的使用

ApplicationContext

@Service(服务存储)

类注解总结

@Bean

方法注解的使用

定义多个对象

Bean的重命名

扫描路径

DI

属性注入

构造方法注入

Setter注入

三种注入方法分析

@Autowired存在的问题

@Primary

@Qualifier

@Resource


Spring可以总结为:包含了众多方法工具的IoC容器

什么是 IoC ?什么是容器

我们通过本篇文章来进行学习

IoC是什么?

理解IoC

IoC(Inversion of Control)控制反转,即控制权反转,指在传统的程序设计中,流程的控制权通常由程序内部实现,而使用IoC,对象对自己所依赖的资源不再负责获取和管理,而是把这些控制权交给外部容器来实现。

什么是容器?

容器:也就是用来容纳物品的装置(如生活中的箱子)。在计算机中,我们容纳的是应用程序和相关组件,因此,容器是一种用于封装应用程序及其所有相关组件的技术

什么是控制权反转?

在传统的程序开发过程中, 当我们需要某个对象时,需要自己通过new创建对象,而IoC有专门的容器来创建这些对象,即IoC容器来控制对象的创建,此时,我们可以将创建对象的任务交给容器,程序只需要依赖注入(DI)就可以了。在此过程中,我们获取对象的过程,由主动(自己创建)变为了被动(从IoC容器中获取),控制权颠倒,因此叫做控制反转

我们通过一个例子来进一步理解IoC:

示例

需求:造一辆车

在进行传统程序开发时,我们的思路是这样的:要造一辆车,首先要有轮胎

99587e79e4b8407388c7d58b6f1d3b9f.jpeg

然后将Tire类主动注入到用Car中

简单代码演示:

Tire:

  1. public class Tire {
  2. private int size;
  3. public Tire(){
  4. this.size = 20;
  5. System.out.println("轮胎尺寸:" + size);
  6. System.out.println("Tire init");
  7. }
  8. public void run(){
  9. System.out.println("Tire");
  10. }
  11. }

Car:

  1. public class Car {
  2. private Tire tire;
  3. public Car(){
  4. tire = new Tire();
  5. System.out.println("Car init");
  6. }
  7. public void run(){
  8. System.out.println("Car");
  9. }
  10. }

然而,当轮胎的尺寸发生变化,需要通过用户的指定来造轮胎,此时,我们需要修改代码:

1552b3cd3bb24fe7937536cb9f52d931.png

对应的,Car也需要进行修改:

d464fce61b2c406f9dc1e90fff3aff52.png

此时,修改底层代码,调用该类的代码都需要修改, 程序的耦合性非常高

在上述程序中,我们在造车时根据车轮的大小设计汽车,车轮一修改,汽车的设计就得修改

我们可以换一种思路:我们不需要完成汽车和轮胎的所有设计,将轮胎外包出去,当轮胎的尺寸发生改变时,我们只需向工厂下订单,工厂就会帮我们造好轮胎

在代码中体现为:我们不在类中创建依赖的对象,而是通过传递(也就是注入)的方式

8f7981611b834381a6579e20dec514a0.png

这样,即使Tire中发生改变,Car本身也不需要修改任何代码

底层类发生变化,调用它的类不用做任何代码,也就实现了代码之间的解耦,从而程序设计更加灵活

在传统的代码中,对象创建的顺序是:Car -> Tire

而改进后的代码,对象创建的顺序是:Tire -> Car

2c04efcb30904b32a5afe59aecf397a3.jpeg

我们可以发现:传统开发中,Car控制并创建了Tire,而改进后,控制权发生了反转,不再是由使用方创建并控制依赖对象了,而是将依赖对象注入到对象中,依赖对象的控制权不再由使用方控制

而 IOC有专门的容器来创建这些对象,即IoC容器来控制对象的创建,使用方需要时,只需将依赖注入就可使用依赖对象

8d5aa0377a67404a874db6ae7fcf0c83.jpeg

为什么要使用IOC

通过上述过程,我们可以看出,使用IoC容器,资源不再由使用资源的双方管理,而是由不使用资源的第三方管理,此时:

  1. 能够降低耦合度:IoC容器可以帮助管理对象之间的依赖关系,将对象的创建和管理交给容器来实现,从而降低了使用资源双方的依赖程度,使得代码更易于理解、维护和扩展。

  2. 简化配置和管理:IoC容器可以集中管理资源,统一进行配置和管理,减少了对资源的手动管理工作,提高了系统的可维护性和管理效率。

  3. 提高了灵活性:通过IoC容器管理对象的依赖关系,可以使系统更加灵活,能够更方便地进行替换、升级或扩展,而不需要修改大量的代码。

DI是什么?

DI(Dependency Injection):依赖注入,在容器运行期间,动态的为应用程序提供运行时所依赖的资源,即程序在运行时需要资源,此时容器就为其提供这个资源

因此,依赖注入可以看做是实现控制反转的一种方式

在示例的改进代码中,是通过构造函数的方式,将依赖对象注入到需要使用的对象中的:

cc2316fb308f46eaa041bd54259cc8fa.jpeg

在了解了 IoC 和 DI的基本概念后,我们来学习 Spring IoC 和 DI 的代码实现

Spring 是一个 IoC容器,作为容器,就具备两个功能:存 和 取

Spring容器管理的主要是对象,而这些被管理的对象,我们称之为 Bean。我们将对象交给 Spring 进行管理,由 Spring 来负责对象的创建和销毁,程序只需要告诉 Spring,哪些需要存取,以及如何取

IoC

要将对象交给IoC容器进行管理,需要使用注解,而Spring框架为更好的服务web应用程序,提供了丰富的注解:

类注解:@Controller @Service @Repository @Component @Configuration

方法注解:@Bean

我们先学习类注解

@Controller(控制器存储)

@Controller的使用

使用@Controller存储bean:

  1. @Controller
  2. public class UserController {
  3. public void hello(){
  4. System.out.println("hello...");
  5. }
  6. }

如何观察这个对象是否已经存在Spring容器中了呢?

若是能从Spring容器中获取这个对象,则这个对象就已经存在Spring容器中了

我们使用ApplicationContext来帮助我们获取对象

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. UserController bean = context.getBean(UserController.class);
  6. bean.hello();
  7. }
  8. }

我们观察运行结果,发现成功从Spring中获取到Controller对象,且执行了Controller的hello方法:

97232c2f02f143599b9a0da14b50f97c.png

若我们将@Controller删除,再观察运行结果:

28be7f18946b4e84b4f0791f853a2b1c.png

此时程序报错:找不到类型为:com.example.demo.controller.UserController 的bean

ApplicationContext

ApplicationContext是什么呢?

ApplicationContext,即Spring上下文

对象交由Spring进行管理,要从Spring中获取对象,首先要拿到Spring的上下文

我们来理解上下文的概念:

在做语文阅读理解的时候,常会遇见这样的问题:请根据上下文,分析你对…的理解 其中的上下文,指的是文章中与某一词语或文句相连的上文和下文

在学习多线程时,应用进行线程切换的时候,在切换之前会将线程的状态信息暂时存储起来,这里的上下文就包括了当前线程的信息,等下次该线程又得到CPU时间时,就能从上下文中拿到线程上次运行的信息

而在Spring框架中,上下文指的是 Spring IoC 容器管理的对象之间的环境和状态。其中包括 bean 的定义、依赖注入、AOP配置等。

在上述代码中,我们是通过类型(DemoApplication.class)来查找对象的,还有其他的方式获取bean

获取bean的方式

ApplicationContext提供了许多获取bean的方式,而ApplicationContext获取bean对象的功能是父类 BeanFactory 提供的功能

bf38ea51cb5247e08e7747a021c19aa4.jpeg

在上述获取bean的方法中,常用的是第1,2,4种

其中涉及到根据名称获取bean,bean的名称是什么呢?

Spring bean 是Spring框架在运行时管理的对象,Spring会给管理的对象起一个名字(例如,学校会给每个学生分配一个学号,根据学号就能够找到对应的学生)

而在Spring中也是如此,为每个对象起一个名字,根据bean的名称,就可以找到对应对象,从而获取对应对象

在分配学号时,学校会根据学生的入学年份、专业、班级等信息分配学号,也就是学号的制定规则

在Spring,是如何命名的呢?Bean的命名约定是什么呢?

命名约定使用Java标准约定作为实例字段名,即 使用小驼峰命名规则

例如:UserController,bean的名称为:userController

根据这个命名规则,我们来获取bean:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. UserController bean = context.getBean(UserController.class);//根据 类型 获取
  6. UserController userController = (UserController) context.getBean("userController");//根据 名称 获取
  7. UserController userController1 = context.getBean("userController", UserController.class);//根据名称 + 类型 获取
  8. System.out.println(bean);
  9. System.out.println(userController);
  10. System.out.println(userController1);
  11. }
  12. }

运行结果:

1acb937559c942d9a7c315773b00dcbe.png

根据结果我们也可以发现:三种方法获取的对象地址一样,这说明获取的对象是同一个

但是,命名时也有一些特殊情况:

  1. @Controller
  2. public class UController {
  3. public void run(){
  4. System.out.println("UController");
  5. }
  6. }
  7. @SpringBootApplication
  8. public class DemoApplication {
  9. public static void main(String[] args) {
  10. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  11. UController uController = (UController) context.getBean("uController");
  12. }
  13. }

此时,运行结果为:

1a95f954a0224c17b35cc2e6683cdad5.png

错误为:没有名称为 uController 的 bean

这是因为,当有多个字符,且第一个和第二个字符都是大写时,要保留原始大小写

因此,UController,bean 的名称为 UController

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. UController uController = (UController) context.getBean("UController");
  6. }
  7. }

我们来总结一下bean的命名约定:

当有多个字符且第一个和第二个字符都是大写时,保留原始大小写

其他情况,则使用小驼峰命名规则

接下来,我们来看@Service

@Service(服务存储)

使用@Service 存储 bean:

  1. @Service
  2. public class UserService {
  3. public void runService(){
  4. System.out.println("service...");
  5. }
  6. }

获取 bean:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. UserService userService = context.getBean(UserService.class);
  6. userService.runService();
  7. }
  8. }

@Repository(仓库存储) @Component(组件存储) @Configuration(配置存储)的使用也是类似的,这里就不再一一演示了

类注解总结

为什么要有这么多的类注解呢?

这与 应用分层 类似,为了在看到类注解后,就能直接了解当前类的用途

@Controller:控制层,接收请求,对请求进行处理,并进行响应

@Service:业务逻辑层,处理具体的业务逻辑

@Repository:数据访问层,也称为持久层,处理数据访问操作

@Configuration:配置层,处理项目中的一些配置信息

@Component:泛指组件,当组件不好归类时,可以使用这个注解

类注解之间的关系:

我们观察 @Controller @Service @Repository @Configuration 和 @Component 的源码:

4aac709c412c4f718e97a6d436b87620.jpeg

@Controller @Service @Repository @Configuration 这些注解里面都有一个注解 @Component,说明 它们 属于 @Component 的 “子类”

@Component 是一个 元注解,也就是可以注解其他类的注解,@Controller @Service等,这些注解被称为@Component的衍生注解

类注解是添加到某个类上的,但在某些情况下也会出现问题问题:

  1. 使用外部包里的类时,没办法添加类注解

  2. 一个类需要多个对象时

此时,我们就需要使用方法注解

@Bean

方法注解的使用

  1. @Data
  2. public class User {
  3. private int id;
  4. private String name;
  5. public User(){}
  6. public User(int id, String name) {
  7. this.id = id;
  8. this.name = name;
  9. }
  10. }
  11. public class Users {
  12. @Bean
  13. public User user() {
  14. return new User(1, "aaa");
  15. }
  16. }

尝试获取:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. User user = context.getBean(User.class);
  6. System.out.println(user);
  7. }
  8. }

运行结果:

c4206d4cfaf04fbe97b3fb7701e67e69.png

程序报错:找不到 类型为 com.example.demo.model.User 的 bean

为什么会报错呢?

这是因为方法注解要配合类注解使用

我们加上类注解:

  1. @Component
  2. public class Users {
  3. @Bean
  4. public User user() {
  5. return new User(1, "aaa");
  6. }
  7. }

运行结果:

cc6f6b24bda24f419fc948b62827ac96.png

定义多个对象

若此时同一个类中有多个对象呢?

  1. @Component
  2. public class Users {
  3. @Bean
  4. public User user1() {
  5. return new User(1, "aaa");
  6. }
  7. @Bean
  8. public User user2(){
  9. return new User(2, "bbb");
  10. }
  11. }

我们根据类型来获取对象:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. User user = context.getBean(User.class);
  6. System.out.println(user);
  7. }
  8. }

运行结果:

75b496b6c48440d1ada6ba07ef5197bd.png

报错显示:期望只有一个匹配,结果发现了两个:user1,user2

我们可以报错信息中看出:@Bean注解的bean,bean的名称就是它的方法名

我们根据名称来获取bean:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. User user1 = (User) context.getBean("user1");
  6. User user2 = (User) context.getBean("user2");
  7. System.out.println(user1);
  8. System.out.println(user2);
  9. }
  10. }

运行结果:

95b7cbf31fd74d2ba03e40b45d504411.png

根据 名称 + 类型来获取bean:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. User user1 = (User) context.getBean("user1", User.class);
  6. User user2 = (User) context.getBean("user2", User.class);
  7. System.out.println(user1);
  8. System.out.println(user2);
  9. }
  10. }

运行结果:

d2ef7b0493d3487c8948775508f6f23b.png

由此可以看出:@Bean可以针对同一个类定义多个对象

Bean的重命名

可以通过设置name属性对Bean进行重命名:

  1. @Component
  2. public class Users {
  3. @Bean(name = {"us1", "user1"})
  4. public User user1() {
  5. return new User(1, "aaa");
  6. }
  7. @Bean
  8. public User user2(){
  9. return new User(2, "bbb");
  10. }
  11. }

此时就可以使用 us1来获取User对象了:

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  5. User user1 = (User) context.getBean("us1");
  6. User user2 = (User) context.getBean("user2", User.class);
  7. System.out.println(user1);
  8. System.out.println(user2);
  9. }
  10. }

运行结果:

ae8b2257fd8643b6b410fe551b88f9df.png

其中 name = 可以省略:

  1. @Bean({"us1", "user1"})
  2. public User user1() {
  3. return new User(1, "aaa");
  4. }

而当只有一个名称时,{}也可以省略:

  1. @Bean("us1")
  2. public User user1() {
  3. return new User(1, "aaa");
  4. }

扫描路径

bean想要生效,需要被Spring扫描

我们修改项目工程的目录结构:

af812ca55c7940e29e397317cb8032e8.png

1477929c44e1434ab7baa86c0eb2e5d7.png

此时再运行代码:

230922a7371440679f915332fcbee5f9.png

程序报错:没有找到名称为us1的bean

为什么没有找到呢?

使用注解声明的bean想要生效需要配置扫描路径,让Spring能够扫描到这些注解

通过 @ComponentScan 来配置扫描路径:

  1. @SpringBootApplication
  2. @ComponentScan({"com.example.demo"})
  3. public class DemoApplication {
  4. public static void main(String[] args) {
  5. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  6. User user1 = (User) context.getBean("us1");
  7. User user2 = (User) context.getBean("user2", User.class);
  8. System.out.println(user1);
  9. System.out.println(user2);
  10. }
  11. }

{} 中可以配置多个包路径

为什么前面没有配置 @ComponentScan 注解也能够扫描?

@ComponentScan 虽然没有显示配置,但其实已经包含在启动类声明注解 @SpringBootApplication 中了

49e0667695094b2a9ffbfe4cb6830d2b.png

其中,扫描的默认范围是 SpringBoot 启动类所在的包及其子包

(在配置类上添加 @ComponentScan 注解,该注解默认会扫描该类所在包下的所有配置类)

因此,将启动类放在我们所希望扫描的包的路径下,这样,定义的bean就可以被扫描到了

DI

在进一步学习了控制反转IoC后,我们来学习依赖注入DI

依赖注入是一个过程,在IoC容器创建bean时,提供运行时所依赖的资源

使用 @Autowired 注解来完成依赖注入

Spring 为我们提供了三种注入方式:

  1. 属性注入 (Field Injection)

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

  3. Setter注入(Setter Injection)

属性注入

属性注入是通过在类的属性上使用 @Autowired 注解或在配置文件中进行配置,将依赖对象注入到类的属性中

我们将UserService类注入到UserController类中:

UserService:

  1. @Service
  2. public class UserService {
  3. public void runService(){
  4. System.out.println("service...");
  5. }
  6. }

UserController:

  1. @Controller
  2. public class UserController {
  3. @Autowired
  4. private UserService userService;
  5. public void hello(){
  6. System.out.println("hello...");
  7. userService.runService();
  8. }
  9. }

获取UserController中的hello方法:

  1. @SpringBootApplication
  2. @ComponentScan({"com.example.demo"})
  3. public class DemoApplication {
  4. public static void main(String[] args) {
  5. ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
  6. UserController userController = context.getBean(UserController.class);
  7. userController.hello();
  8. }
  9. }

运行结果:

177671a514554377a499337d70136a59.png

若去掉 @Autowired:

8b4d62b464454ad7ac048aaa75804379.png

程序报错:不能调用 com.example.demo.service.UserService.runService(),因为 this.userService 为空

构造方法注入

构造方法注入是在类的构造方法中实现注入:

  1. @Controller
  2. public class UserController {
  3. private UserService userService;
  4. @Autowired
  5. public UserController(UserService userService){
  6. this.userService = userService;
  7. }
  8. public void hello(){
  9. System.out.println("hello...");
  10. userService.runService();
  11. }
  12. }

运行结果:

63ac3fc92d1e43758ac77cf234933367.png

若此时类中只有一个构造方法,则 @Autowired 注解可以省略:

  1. @Controller
  2. public class UserController {
  3. private UserService userService;
  4. // @Autowired
  5. public UserController(UserService userService){
  6. this.userService = userService;
  7. }
  8. public void hello(){
  9. System.out.println("hello...");
  10. userService.runService();
  11. }
  12. }

但若类中有多个构造方法,此时就需要添加 @Autowired 注解来明确指定使用哪个构造方法

  1. @Controller
  2. public class UserController {
  3. private UserService userService;
  4. public UserController(){}
  5. @Autowired
  6. public UserController(UserService userService){
  7. this.userService = userService;
  8. }
  9. public void hello(){
  10. System.out.println("hello...");
  11. userService.runService();
  12. }
  13. }

若此时去掉 @Autowired 注解,程序报错:

32d7a2306eb3408f91da933ffa81a768.png

Setter注入

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

  1. @Controller
  2. public class UserController {
  3. private UserService userService;
  4. @Autowired
  5. public void setUserService(UserService userService){
  6. this.userService = userService;
  7. }
  8. public void hello(){
  9. System.out.println("hello...");
  10. userService.runService();
  11. }
  12. }

此时,若 去掉 @Autowired:

32cd564a6330486f95fc2920f5817c38.png

同样的,程序报错

三种注入方法分析

属性注入:

优点:

简洁方便,可以直接在属性上进行注入,代码简洁,不需要编写额外的构造方法或 Setter 方法

缺点:

  1. 只能用于IoC容器

  2. 不能注入 final 修饰的属性

构造函数注入:

优点:

  1. 可以注入 final 修饰的属性

  2. 注入的对象不会被修改

  3. 依赖对象在使用前一定会被完全初始化(因为依赖是在类的构造方法中执行的,而构造方法在类加载阶段就会执行)

  4. 通用性好,构造方法是JDK支持的,更换框架后也是适用的

缺点:

注入多个对象时,代码量相对较多

Setter注入:

优点:

  1. 方便在类实例后,重新对该对象进行配置或注入

  2. 可选依赖,可以只提供部分 Setter 方法,不影响其他依赖的注入

缺点:

  1. 不能注入 final修改的属性

  2. 注入对象可能会发生改变(setter方法可能被多次调用,就有被修改的风险)

  3. 需要为每个需要注入的属性编写相应的 Setter 方法,增加了代码量

因此, 选择使用哪种依赖注入方式取决于具体的需求和场景。

@Autowired存在的问题

若同一类型中存在多个bean,此时适用@Autowired会存在问题:

  1. @Controller
  2. public class UserController {
  3. @Autowired
  4. private User user;
  5. public void hello(){
  6. System.out.println("hello...");
  7. System.out.println(user);;
  8. }
  9. }

运行结果:

8c223fa334e64f3399417e9bbcf196cb.png

程序报错:UserController 需要一个 bean,但是发现了两个,即非唯一的bean

如何解决该问题呢?

其实报错信息下面就给出了解决方法:

@Primary

当多个类型相同的bean注入时,加上 @Primary 注解,来确定默认的实现:

  1. @Component
  2. public class Users {
  3. @Primary//指定 该 bean 为默认bean实现
  4. @Bean
  5. public User user1() {
  6. return new User(1, "aaa");
  7. }
  8. @Bean
  9. public User user2(){
  10. return new User(2, "bbb");
  11. }
  12. }

运行结果:

58382e0f3ab24236b68925bc9f99a5f7.png

@Qualifier

使用 @Qualifier 注解,指定当前要注入的对象,在 @Qualifier 的 value属性中,指定注入的 bean的名称,@Qualifier注解不能单独使用,必须配合 @Autowired 使用

  1. @Controller
  2. public class UserController {
  3. @Qualifier("user2")
  4. @Autowired
  5. private User user;
  6. public void hello(){
  7. System.out.println("hello...");
  8. System.out.println(user);;
  9. }
  10. }

运行结果:

ccd22a7e508449009b0f73996ffa55be.png

@Resource

@Resource注解,是按照 bean 的名称进行注入,通过 name 属性指定要注入的 bean 的名称

  1. @Controller
  2. public class UserController {
  3. @Resource(name = "user1")
  4. private User user;
  5. public void hello(){
  6. System.out.println("hello...");
  7. System.out.println(user);;
  8. }
  9. }

运行结果:

2d13416937d44446a060d6ffbcead46a.png

@Autowired 与 @Resource 的区别

@Autowired 是 Spring 框架提供的注解,而 @Resource 是JDK 提供的注解

@Autowired 默认是按照类型注入的,而 @Resource 是按照名称注入的,相比于 @Autowired,@Resource 支持更多的参数设置

发表评论

表情:
评论列表 (有 0 条评论,160人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring IoCDI

    为什么要有这么多的类注解呢?这与 应用分层 类似,为了在看到类注解后,就能直接了解当前类的用途@Controller:控制层,接收请求,对请求进行处理,并进行响应@Ser...

    相关 Spring IoCDI

    Spring是一个依赖注入(Dependency Injection, DI)和控制反转(Inversion of Control, IoC)容器。IoC意味着应用程序不...

    相关 Spring-框架-DIIoC

    DI:依赖注入,在一个java类中需要依赖另外一个类,通过spring容器在需要的时候把这个类注入到里面         运行时期,通过外部程序注入。一般是调用者创建被调用者

    相关 spring IocDI

    spring的“控制反转”和“依赖注入”,个人看来是一个意思。 传统java程序中,使用一个对象的时候,都需要先new Object()创建一个新对象,才能使用。对象的控制权

    相关 SpringIOCDI

    IoC IoC(控制反转),是指在程序的设计中,实例不再由调用者来创建,而是由Spring容器来创建。 Spring容器会负责控制程序之间的关系,而不是由程序代码直接控

    相关 SpringIOCDI

    学习了Spring框架的人,都会听到过IOC和DI这两个词,对于初学者来说,这两个词的概念模糊不清,很难理解,就我对控制反转和依赖注入进行简单的解释。以前创建对象的方式以及依赖