• Spring之IoC


    目录

    IoC的引入

    为什么要叫IoC(控制反转)

    IOC也叫依赖注入(DI)

     如何给SpringIoC容器里面卖对象呢?

     bean的概念​

     基于XML配置的做法

             直接卖配方的做法

            默认选择无参构造

            指定构造方法

             直接生产好对象进行售卖

            静态工厂

            实例化工厂

    基于注解的做法

    直接卖配方的方式

    直接生产好对象进行售卖

    Ioc容器创建的方法

    Bean获取的方法


    IoC的引入

    前言

    当我们在实际开发的时候,代码量规模会变的非常庞大,程序中对象的数据会随着几何级别的增长,对象和对象之间的关系也会以指数关系增长,对于程序员来说,如何组织和维护对象之间的关系变得非常困难,其中关系可以抽象成A对象依赖于B对象的关系

    用生活例子来举例为什么要引入Ioc

    • IoC(控制反转)思想依赖DI(依赖注入)形式,两者只是从不同的角度去描述同一个事情,随着软件规模的发展,我们的对象经济也不可避免的从小农经济发展到商品经济
    • IoC Container(Ioc容器):它是一个容器,放的是对象——就是一个对象市场,里面放置的就是待出售的对象
    • 作为对象的买方,我们只在代码的中声明我们的依赖(需要购买)哪些类型的对象,最终的对象就是通过Spring IoC这套流程注入到我们的代码里(类似对象送货上门) 

    没引入Ioc之前

    • 描述的就是这样的一个齿轮组,它拥有多个独立的齿轮,这些齿轮相互啮合在一起,协同工作,共同完成某项任务。我们可以看到,在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转。
    • 齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似。对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。现在,伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。所以提出了IoC思想

     引入IoC之后

    • 由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。 

    为什么要叫IoC(控制反转)

    •   软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
    •  软件系统在引入IOC容器之后,这种情形就完全改变了,如图2所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

    IOC也叫依赖注入(DI)

    • 既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

      

     如何给SpringIoC容器里面卖对象呢?

    • 自己生产好对象,再卖到IoC容器中,分为静态工厂方法和实例化工厂方法
    • 将生产对象的配方(告诉Spring使用什么方式去实例化对象)告诉IoC容器,最终售卖的对象直接有IoC容器生产(这种使用的比较多),其实实质就是通过我们的构造方法创建对象

     bean的概念

    • IOC容器负责对象的创建和初始化等一系列工作,被创建或者被管理的对象在Ioc容器中统称为Bean

     一种基于XML配置的做法

    (学习阶段方便,逻辑上比较清晰,但是实际中因为XML很容易变的很混乱,所以使用的比较少)

     直接卖配方的做法

    • 售卖一个使用无参构造方法实例化的对象
    • 可以指定Spring在实例化的时候调用我们的哪个构造方法

    作为纯卖方和买方的关系

    默认选择无参构造

    •  其实实现这种,Spring在内部给我们做了很多的工作

    指定构造方法

    基于又作为买方又作为卖方(依赖注入的应用)

    • 构造方法的注入
    • setter方法注入
    • 两种类型的注入,简单类型(String,基本数据类型),引用类型(靠依赖注入)

    用构造方法注入属性

    • 产生依赖关系。Zoo是买方又是卖方,Zoo又作为卖方把对象放到市场卖  

    用setter方法来注入属性

    自动装配

    • Ioc容器根据bean所依赖的的资源容器中自动查找并注入到bean的过程叫自动装配,所以我们知道我们需要只能注入的是引用类型,不能简单类型的注入,而且被注入的也是bean
    • 自动装配必要提供setter方法,需要我们在bean标签配置上autowired属性
    • 属性可选值:byType,byName,constructor,default, no

     直接生产好对象进行售卖

    • 以静态工厂的方法售卖对象(自己new一个对象再放到IoC容器去卖)
    • Java所有的代码都挂靠在某个方法里,方法又得挂靠在某个类上,如果不想用对象直接调用方法,那么就只能使用静态方法,这种专门实例化对象的方法一般称为工厂方法(factory method)

    静态工厂

    实例化工厂

    •  先给我们的实例化工厂的类创建一个bean对象,使用实例化工厂创建对象的时候,用factory-bean来指明我们的实例化工厂的bean

     FactoryBean

    • 因为我们的实例化工厂创建完对象就没作用了,而且实例化工厂创建对象的方法需要配置
    • 对于实例工厂Spring提供了一个通用的实例化工厂。来简化我们使用实例化工厂这种方法 

     总结

     

    • 我们要明确谁是纯卖方,谁是纯买方,其中我们的依赖注入是发生在【又是卖方又是买方】
    • 因为只有是买方,Spring才需要为其注入
    • 因为是卖方,Spring才能控制对象的实例化过程,才能有能力在实例化的过程期间为其进行注入
    • IoC(控制反转只是一种理念),其中很多时候通过注入依赖(DI)开具体实现,依赖注入是发生在Sring管理的不同bean之间的,Spring 是IoC市场占主导地位的一款产品,所以我们有必要学习Spring,IoC只是Spring的核心能力

     bean的配置

    •       表示创建一个bean给Ioc容器管理
    • 属性 id:表示使用Ioc容器通过唯一的id来获得对应的bean
    • 属性 class:表示要管理对应bean的类的全名称,或者是工厂方法的所在的类
    • 属性 name:表示管理bean的别名,可以定义多个,可以使用 逗号 分号 ' '分割 
    • 属性 scope:表示bean的作用范围,可以是singleton单例(默认),prototype非单例
    • 属性 factory-method:表示对应工厂类的创建bean的方法
    • 属性 factory-bean:在我们实例化工厂方法的时候,写入我们实例化工厂的bean对象
    • 属性init-method:表示我们的初始化方法(加载一些数据),这个方法应该在实例化和设置属性之后
    • 属性destroy method:表示我们在销毁一个bean对象(关闭容器)之前进行一些方法
    • 属性autowried:表示我们的bean的依赖注入,使用自动装配的不同方式,或者是不使用
    • 标签,表示用setter方法来进行属性的注入,name表示属性的名称,ref属性:表示注入的是引用类型,写的值是bean的id  value:表示简单类型的注入,写的值就是直接的值,比如int 10,String "liusc"
    • 标签,表示用构造方法来进行属性的注入,name表示属性的名称,ref属性:表示注入的是引用类型,写的值是bean的id  value:表示简单类型的注入,写的值就是直接的值,比如int 10,String "liusc"
    • 用来加载对应的properties配置文件,通过注入依赖的时候,使用value=${对应的key值}来获得properties的信息

    Java提供的初始化和销毁前的操作

    Spring bean 通过实现 InitializingBean ,DisposableBean 接口实现初始化方法和销毁前操作

    1. @Component
    2. public class Student implements InitializingBean, DisposableBean {
    3. @Override
    4. public void destroy() throws Exception {
    5. System.out.println("DisposableBean destroy");
    6. }
    7. @Override
    8. public void afterPropertiesSet() throws Exception {
    9. System.out.println("InitializingBean afterPropertiesSet");
    10. }
    11. }

    为什么bean默认是单例

    • 一般我们交给容器管理的bean是表现层,业务层,数据层,工具对象,这是都是一些过程对象
    • 不适合交给管理的,封装实体的域对象,也就是我们封装我们数据库一行数据的数据对象

    基于注解的做法

    • 上面的通过XML中的标签,一个个的添加让Spring管理的对象——注册的过程,但是如果要管理的对象太多的话,也是比较麻烦的,XML文件也会比较混乱
    • 所以我们通过要注册的类(交给Spring管理)的上面添加注解+Spring在启动过程下会去包下的所有类来确定哪些类会被Spring管理 (通过我们的Ioc容器对应加载的XML文件来确定,会在XML文件下指明要扫描哪些包下面的类)

    直接卖配方的方式

    例子使用Compent来表示Bean注册

    利用注解进行Spring注册:前提是需要指定的包下的类

    • @Component 组件(如果其他注解的意义都用不上,就可以用@Component)
    • @Controller 控制器(当一个类表示控制器的作用,想注册到Spring中,就可以用Controller)
    • @Service 服务(当一个类提供服务功能的时候)
    • @Repository 仓库(当一个类提供从MySQL(也可以是其他存储软件)中进行数据的读写时)
    • @Configuration 配置(设置当前这个类为配置类),也就是表示我们的bean配置的xml文件,然后用CompenentScan()来写我们要扫描的类
    • 这五个注解在进行类注册的这个作用的时候,对Spring执行代码没有上面区别(但是@Configuration是有点区别的),主要是给程序员看到

    直接生产好对象进行售卖

    • 方法必须出现在已经注册到Spring类中(用@Component系列修饰的类)原则上用哪个注释都行,但是更建议@Configuration注释修饰
    • @Bean注释修饰方法

     

     如何选择这两者注册的方法

    •  当注册是类,是我们自己写的,我们能添加注解去修饰,就使用Component系列去进行注册
    • 当这个类不是我们自己写的,不能修改别人的代码,我们就为类添加注解,然后使用@Bean的工厂方式进行注册

    使用bean:全部都是注入的方式(前提是使用bean的类并且得被Spring管理起来),作为买方和卖方,也就是自动装配

    • 构造方法注入,用@Autowried修饰构造方法,虽然不加也可以,但是建议带上(因为方便人识别) 
    • setter方法注入,用@Autowried修饰setter方法
    • 直接属性注入,用@Autowried修饰我的属性。写的是我们的bean的ID
    • 在进行注入的时候,只有这个类注册到了Spring下,被Spring实例化出来才能进行注入,如果是我们自己用代码手动new出来的对象是无法进行注入的
    • 如果是简单数据类型,那我们就是@Value来传入需要的数据
    • 或者在我们的bean修饰的工厂方法的形参也需要对应的bean,采用自动装配,@Autowried可以不写

     对于Bean修饰的工厂方法也可以通过形参的形式进行注入

    bean的配置用注解实现

    • bean的注册,用直接给配方的方法(采用构造方法),使用@Component(@Controller,@Service,@Repository),其中括号中写的值就是bean的id
    • @Configuration:表示这个类是我们的配置类,类似于我们注册bean的xml文件,可以用这个类.class来获得对应的Ioc容器(@ComponentScan()来写明对应要扫描的类)
    • @Scope:表示这个bean的作用范围
    • @PostConstruct:表示是对应的init-method方法,在bean实例化和属性注入之后
    • @PreDestory:表示是我们的destory-method方法,销毁之前执行的方法
    • @Autowried:表示我们的自动装配,装配我们的bean对象,也就是对应的引用类型
    • @Value:表示自动装配的是我们简单类型的数据,这个主要用法是可以写入我们的配置文件的信息,用${key},得到对应的value值
    • @PropertySource:表示来配置我们的propeerties文件

    Ioc容器创建的方法

    • 第一种通过加载类途径下的xml文件,也就是加载相对路径
    • 第二种加载文件系统途径下的xml文件,也就是我们文件的绝对路径 

    Bean获取的方法

    • 都是通过Ioc容器.getBean();
    • 1通过bean的id获取
    • 2通过bean的id和对应的class类型获得
    • 3通过bean的类型直接获取——前提这个类的bean只能有一个
    • 4依靠我们的Spring的自动装配

  • 相关阅读:
    C++ Reference: Standard C++ Library reference: C Library: cwchar: putwchar
    php调取java类方法,jar包,亲测已上线!windows!
    echarts让设置legend宽度不生效
    React+echarts (echarts-for-react) 画中国地图及省份切换
    【Java学习】语法:包、权限修饰符、final、常量、枚举、抽象类、接口
    ECharts数据可视化(案例)
    Java小游戏:趣味猜数字
    ArcEngine(五)用ICommand接口实现放大缩小
    王道数据结构二叉树算法大题代码总结
    c# --- 抽象类,密封类与子类的构造函数
  • 原文地址:https://blog.csdn.net/qq_50985215/article/details/126549953