控制反转(IoC)是什么?

2024-06-13 1140阅读

文章目录

  • 二、IoC是什么?
  • 三、具体程序开发举例
  • 四、控制反转(IoC)有什么用?
  • 五、Bean的存储
    • getBean
    • getBean传参注意
      • 小驼峰
      • 两个连续大写字母开头的类名
      • 1.1@Controller(控制器存储)
      • 1.2@Service(服务存储)
      • 1.3@Repository(仓库存储)
      • 1.4@Component(组件存储)
      • 1.5@Configuration(配置存储)
      • 五种类注解的联系
      • 方法注解@Bean
        • 当有多个构造方法时,需要使用类名来获取bean对象。
        • 当构造方法有参数时,需要创建参数对应类型的方法
        • 在这里插入图片描述

          学习Spring框架的小伙伴肯定都知道Spring框架的核心是IoC容器和AOP模块。

          也都听说过 Spring是包含众多工具方法的IoC容器。

          IoC容器是Spring框架的底层基础,负责管理对象的创建和对象依赖关系的维护

          IoC是一种思想,而DI就是实现这个思想的一种方法。

          那么本文就带大家来了解什么是IoC

          二、IoC是什么?

          Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。

          在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制,对于spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。

          在开发中的表现就是:
          当需要一个对象时,不再自己通过new来创建对象,而是把创建对象的任务交给容器,在程序中只需要依赖
          注入(DI)。这个容器就成为IoC容器。
          

          三、具体程序开发举例

          现在有这样的需求:造一辆车

          我们根据需求来梳理思路:

          我们先设计轮子(Tire),然后根据轮子的大小来设计地盘(Bottom),然后根据底盘设计车身(Framework),然后再由车身设计出整个汽车。

          这里就出现了一个依赖关系:

          汽车依赖车身,车身依赖底盘,底盘依赖轮子

          控制反转(IoC)是什么?

          public class Main {
              public static void main(String[] args) {
                  Car car = new Car();
                  car.run();
              }
          }
          public class Car {
              private Framework framework;
              public Car() {
                  framework = new Framework();
                  System.out.println("car init ....");
              }
              public void run(){
                  System.out.println("car run ....");
              }
          }
          public class Framework {
                  private Bottom bottom;
                  public Framework() {
                       bottom = new Bottom();
                      System.out.println("framework init....");
                  }
          }
          public class Bottom {
              private Tire tire;
              public Bottom() {
                  tire = new Tire();
                  System.out.println("bottom init....");
              }
          }
          public class Tire {
              private int size = 17;
              public Tire( ){
                  System.out.println("Tire init....");
              }
          }
          

          运行程序

          控制反转(IoC)是什么?

          当车轮的尺寸需要随着不同的需求而变更时,那么底盘,车身,汽车都要受到波动。

          控制反转(IoC)是什么?

          这样的设计,导致耦合太高,当一部分的代码需求变更时,会影响其他很多代码,增加了改动的成本

          那么如何解决呢?

          我们尝试换⼀种思路, 我们先设计汽⻋的⼤概样⼦,然后根据汽⻋的样⼦来设计⻋⾝,根据⻋⾝来设计

          底盘,最后根据底盘来设计轮⼦. 这时候,依赖关系就倒置过来了:轮⼦依赖底盘, 底盘依赖⻋⾝,

          ⻋⾝依赖汽⻋

          控制反转(IoC)是什么?

          我们可以尝试不在每个类中⾃⼰创建下级类,如果⾃⼰创建下级类就会出现当下级类发⽣改变操作,

          ⾃⼰也要跟着修改.

          此时,我们只需要将原来由⾃⼰创建的下级类,改为传递的⽅式(也就是注⼊的⽅式),因为我们不

          需要在当前类中创建下级类了,所以下级类即使发⽣变化(创建或减少参数),当前类本⾝也⽆需修

          改任何代码,这样就完成了程序的解耦.

          控制反转(IoC)是什么?

          public class Main {
              public static void main(String[] args) {
                  Tire tire = new Tire(18,"red");
                  Bottom bottom = new Bottom(tire);
                  Framework framework = new Framework(bottom);
                  Car car = new Car(framework);
                  car.run();
              }
          }
          

          这样做以后,我们传入的都是对象,当一个对象属性发生改变时,不会影响其他部分的正常运行。

          达到解耦合的作用

          我们发现了⼀个规律,通⽤程序的实现代码,类的创建顺序是反的,传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,⽽改进之后的控制权发生的反转,不再是使⽤⽅对象创建并控制依赖对象了,⽽是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由当前类控制了.

          这样的话, 即使依赖类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。

          控制反转(IoC)是什么?

          四、控制反转(IoC)有什么用?

          1. 资源集中管理: IoC容器会帮我们管理⼀些资源(对象等), 我们需要使⽤时, 只需要从IoC容器中去取就可以了
          2. 解耦合:我们在创建实例的时候不需要了解其中的细节, 降低了使⽤资源双⽅的依赖程度

          看到这是不是还有点懵,还没真正的搞懂什么是IoC,那么接下来就会使用来让你真正的认识IoC。

          五、Bean的存储

          在这一部分,会真正的使用IoC,来对IoC有一个深刻且全面的认识。

          首先我们先搞清楚概念Bean是什么东西?

          根据Bing搜索:

          控制反转(IoC)是什么?

          简而言之Bean就是容器内的对象。

          这里的注解就是告诉Spring这里的内容已经放置到容器内了

          要将创建对象的控制权交给Spring,就要事先声明给Spring哪些是需要进行控制的。

          那么实现方式有两种

          1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
          2. 方法注解:@Bean

          getBean

          ApplicationContext context = SpringApplication.run(IoCApplication.class, args);
          

          这是启动类的代码,这里返回的ApplicationContext就是Spring的运行环境。

          这里的context就相当于是一个容器了,那么要如何从容器中拿到对象呢?

          这里就要使用getBean这个方法了。

          getBean方法括号内常用的传参方式有三种

          1. 根据bean的名称取
          2. 根据bean的类型取
          3. 根据bean的名称和类型取

            控制反转(IoC)是什么?

          控制反转(IoC)是什么?

          控制反转(IoC)是什么?

          举例如下

          这是在后面要讲解的@Controller注解

          @Controller
          public class Usercontroller {
              public void DoController() {
                  System.out.println("Do Controller....");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                 ApplicationContext context =  SpringApplication.run(IoCApplication.class, args);
                  Usercontroller  bean  = context.getBean(Usercontroller.class);
                  bean.DoController();
              }
          }
          

          控制反转(IoC)是什么?

          getBean传参注意

          这里要注意,使用名称来获取时,使用小驼峰的命名规范。

          当类名前两个字母是连续大写时,就不需要变成小驼峰。

          如果需要调用方法,这里需要转型

          小驼峰

          这有两个注意点:

          1. 小驼峰

            控制反转(IoC)是什么?

            类的方法名是UserController

            而我们使用getBean的方法名来获取bean对象的时候,就需要将类名转换为小驼峰的形式,也就是userController

          控制反转(IoC)是什么?

          2. 类型转换

          在使用类名获取bean对象时,我们还要进行类型的转换!

          两个连续大写字母开头的类名

          这时就不需要变成小驼峰的形式。

          这是bean的名称的内部实现方式的源码

          控制反转(IoC)是什么?

          1.1@Controller(控制器存储)

          @Controller
          public class Usercontroller {
              public void DoController() {
                  System.out.println("Do Controller....");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                 ApplicationContext context =  SpringApplication.run(IoCApplication.class, args);
                  Usercontroller  bean  = context.getBean(Usercontroller.class);
                  bean.DoController();
              }
          }
          

          控制反转(IoC)是什么?

          在平常,我们调用对象的方法,首先需要先创建对象,然后再调用对应的方法。

          现在我们

          1.2@Service(服务存储)

          @Service
          public class UserService {
              public void DoService(){
                  System.out.println("do service...");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                 ApplicationContext context =  SpringApplication.run(IoCApplication.class, args);
                 //从context中获取对象
                 // Usercontroller  bean  = context.getBean(Usercontroller.class);
                 //  bean.DoController();
                  UserService bean1 = context.getBean(UserService.class);
                  bean1.DoService();
              }
          }
          

          控制反转(IoC)是什么?

          getBean方法括号内常用的传参方式有三种

          通过类型来获取
          通过名称来获取
          通过类型和名称一同获取
          

          控制反转(IoC)是什么?

          控制反转(IoC)是什么?

          这里要注意,使用名称来获取时,使用小驼峰的命名规范。

          当类名前两个字母是连续大写时,就不需要变成小驼峰。

          如果需要调用方法,这里需要转型

          控制反转(IoC)是什么?


          控制反转(IoC)是什么?

          1.3@Repository(仓库存储)

          @Repository
          public class UserRepository {
              public void DoRepository() {
                  System.out.println("Do Repository...");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                  ApplicationContext context = SpringApplication.run(IoCApplication.class, args);
               
                  UserRepository bean2 = context.getBean(UserRepository.class);
                  bean2.DoRepository();
              }
          }
          

          控制反转(IoC)是什么?

          1.4@Component(组件存储)

          @Component
          public class UserComponent {
              public void DoComponent(){
                  System.out.println("Do Component");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                  ApplicationContext context = SpringApplication.run(IoCApplication.class, args);
           
                  UserComponent bean3 = context.getBean(UserComponent.class);
                  bean3.DoComponent();
              }
          }
          

          控制反转(IoC)是什么?

          1.5@Configuration(配置存储)

          @Configuration
          public class UserConfiguration {
              public void DoConfiguration() {
                  System.out.println("UserConfiguration");
              }
          }
          
          @SpringBootApplication
          public class IoCApplication {
              public static void main(String[] args) {
                  ApplicationContext context = SpringApplication.run(IoCApplication.class, args);
           
                  UserConfiguration bean4 = context.getBean(UserConfiguration.class);
                  bean4.DoConfiguration();
              }
          }
          

          控制反转(IoC)是什么?

          五种类注解的联系

          控制反转(IoC)是什么?

          查看@Controller / @Service / @Repository / @Configuration的源码发现,这些注解都包含一个@Component的注解,说明四个注解都是@Component的子类。

          方法注解@Bean

          @Bean必须搭配类注解才能使用

          public static void main(String[] args) {
                  ApplicationContext context = SpringApplication.run(IoCApplication.class, args);
                  UserInfo bean = context.getBean(UserInfo.class);
                  System.out.println(bean);
              }
          
          @Data
          public class UserInfo {
              private Integer id;
              private String name;
              private Integer age;
          }
          
          public class BeanConfig {
              @Bean
              public UserInfo getUserInfo() {
                      UserInfo userInfo =  new UserInfo();
                      userInfo.setAge(18);
                      userInfo.setId(11);
                      userInfo.setName("张三");
                      return userInfo;
              }
          }
          

          我们运行,出现如下报错,这是因为如果我们要使用@Bean时, 必须要在类前,也就是在BeanConfig这部分代码中,提前声明告诉Spring这里面有需要管理的对象。

          控制反转(IoC)是什么?

          此时在BeanConfig中加入@Configuration注解,就运行成功了。

          当有多个构造方法时,需要使用类名来获取bean对象。

          控制反转(IoC)是什么?

          如上代码,有两个构造方法,此时再用类型传参就会报错

          这时就需要使用类名来传参

                  UserInfo userInfo = (UserInfo)context.getBean("getUserInfo");
                  System.out.println(userInfo);
          

          这时就能获取到UserInfo对象了。

          当构造方法有参数时,需要创建参数对应类型的方法

          这时就需要有参数的方法getUserInfo时,就需要再使用@Bean来创建一个String类型的name对象。

          控制反转(IoC)是什么?

          以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]