Spring中的IOC控制翻转容器使用与总结

Spring框架应该是作为Java开发耳熟能详的一个,并且要能够熟练掌握。但是里面知识点的零碎可能随着时间的流逝,一些知识也会变的陌生起来。Spring这一系列的文章主要是将自己对Spring的一些认识梳理一下,其中这篇文章讲的主要是IOC相关的。

在很早的时候也写过两篇将IOC容器的文章,供君参考,这篇文章更多的是对IOC中相关知识的梳理,内容在下面的两篇文章中也都有:

https://blog.youkuaiyun.com/lmlzww/article/details/105363279?spm=1001.2014.3001.5502

https://blog.youkuaiyun.com/lmlzww/article/details/105418953?spm=1001.2014.3001.5502

Spring是一个体量小、可以独立使用的轻量级框架,开源并且是为简化企业应用开发的复杂性而生。就像其中的IOC是为Bean容器的创建以及降低耦合度而生,而AOP作为动态代理为原理实现的特性,也可以从分离业务逻辑以及非业务逻辑的角度来降低系统的耦合行,提升可扩展能力,他的优势如下:

  • 支持AOP框架
  • 方便测试
  • 可以很好的组合第三方框架
  • 方便事务管理

0、IOC容器是什么

那么IOC容器到底是什么呢?我们可以分开理解:IOC(Inversion of Control)控制反转、容器——在IOC容器中提供了提供了我们在配置文件中配置的对象,程序中使用到的对象我们可以通过这个获取,而不需要在程序中通过new创建,正是因为不需要通过new创建了,所以对对象的创建权利实现了翻转,以前通过new创建对象对于程序来说是主动的,但是现在对象是通过Spring框架的IOC容器提供得来的,相对来说是被动的。

在我们学习IOC的时候实际也就围绕两个核心展开——实例的创建、实例的应用,对象的创建主要关注亮点一个是对象创建的形式、还有一个就是对象各种属性的赋值也就是说依赖注入。既然有对象的创建那么就会有他的生命周期,这里要与AOP中的区分开来。总而言之一切都是围绕对象展开的!

1、IOC容器的底层实现原理

底层主要通过xml解析、工厂模式、反射(通过获取到class文件从而再来创建具体对象)三个模块进行实现。主要的一个流程就是:

获取XML并进行解析——>根据配置配置信息获取到class文件——>根据class生成对象实例

2、IOC的容器对象

如果要是用指定的容器获取对象那么框架为给我们默认单例、多例,如果要是我们指定了单例、多例那么系统也会给我们选默认的容器。

  • BeanFactory:内部实现的,一般是IOC容器内部使用,开发人员一般不适用;加载配置文件的时候并不会直接创建里面的对象,只有在获取或是使用的时候才会去创建,是多例模式
  • ApplicationContext:是上面的一个子类;加载配置文件的时候就会完成对对象的创建,单例模式,单例的时候需要考虑类公共属性存在的一个线程安全问题

ApplicationContext是一个接口,他有很多不同类型的实现子类:
在这里插入图片描述

3、IOC容器对象的创建

IOC帮助我们完成实例的创建,我们可以理解通常我们有几种对象的创建方式,实际上就是构造函数以及工厂方法,工厂方法又根据方法是否为静态的可以分为两种配置形式。

普通Bean——指定什么类型就是什么类型
  • 构造函数构造
  • 通过普通方法构造
  • 通过静态方法构造
 <!-- 第一种方式:使用默认构造函数创建。
            在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
            采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
<!-- 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)-->
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
 
<!-- 第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)-->
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
  • id: 给对象起一个别名,用来获取对象
  • class: 类的全路径
  • name: 与id作用相同,相对于id来说可以添加一些特殊 字符,主要服务于struct1框架,现在不用
工厂Bean——XML中定义的bean类型可以与返回的类型不一样
  • 创建类,让这个类作为工厂Bean,实现接口FactoryBean

  • 实现接口里面的方法实现的方法中返回的Bean类型
    在这里插入图片描述

注解形式的实现

上面说的是通过xml配置文件形式来进行容器对象创建进行制定,通过xml我们也可以使用p名称空间注入简化xml中的配置。开发中我们更常用的是注解形式:@Component、@Service、@Controller、@Repository这四个注解功能是一样的都可以用来创建Bean实例,主要是为了开发人与进行区分。

4、IOC容器的依赖注入

这里说的容器依赖注入理解为一个Bean依赖于另一个Bean,也就是说以属性的形式存在,属性我们通常会设置为private,这时候想要对对象进行赋值就有两种方式:

  • 构造函数
 <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="泰斯特"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="birthday" ref="now"></constructor-arg>
 </bean>
  <!-- 配置一个日期对象,这里体现的就是可以传递其他的Bean类型 -->
<bean id="now" class="java.util.Date"></bean>
  • setter方法
<bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
        <property name="myStrs">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>
 
        <property name="myList">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
 
        <property name="mySet">
            <array>
                <value>222222</value>
            </array>
        </property>
 
        <property name="myMap">
            <props>
                <prop key="testC">ccc</prop>
                <prop key="testD">ddd</prop>
            </props>
        </property>
 
        <property name="myProps">
            <map>
                <entry key="testA" value="aaa"></entry>
                <entry key="testB">
                    <value>BBB</value>
                </entry>
            </map>
        </property>
    </bean>
xml中间配置集合抽取出来需要引入util名称空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wq6xznpR-1663328880605)(F:\typroa\aimages\image-20220914200156746.png)]

如果注入的依赖有特殊值,则需要特殊处理:
  • 设置为null值是通过null标签,而非是标签里的value值

  • 特殊字符的话通过转义符&lt或是&gt ;把特殊符号内容写到cdata的接口
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmlklHGv-1663328880606)(F:\typroa\aimages\image-20220914191053655.png)]

注入的如果是对象进行级联赋值或是内部Bean的使用
  • 一级节联赋值
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmyaPXMm-1663328880606)(F:\typroa\aimages\image-20220914192958367.png)]
  • 多级节联赋值,当使用JSON表达能力进行使用需要给dept属性给一个get方法
    在这里插入图片描述
注解方式赋值

上面也说到依赖注入实际上就是给属性赋值,那么我们也可以通过注解的方式来实现:

  • @AutoWired:根据属性类型进行自动注入

  • @Qualifier:根据属性的名称进行注入,需要与@Autowired配合使用,当一个接口有多个实现类的时候就可以根据名称进行赛选了

  • @Resource:可以根据属性进行注入也可以根据名称进行注入,在使用

  • @Value:注入普通类型的属性

这里可以联想到容器对象构建的时候@Component、@Bean等注解可以给穿件的Bean命名

5、IOC操作中Bean的声明周期

  • scope属性:singleton—单实例(加载配置文件的时候就会创建一个单实例对象);prototype—多实例对象(不是在加载配置文件的时候创建对象而是在调用getBean的时候创建多实例对象);request—每次创建对象会凡在request中;session—创建之后放在session中

  • 声明周期——从对象的创建到对象的销毁

    • 通过构造器创建bean

    • 为bean的属性设置和对其他bean的引用

    • 初始化之前吧bean实例传递给bean的前置处理器方法

    • 调用bean的初始化方法(需要进行配置)

    • 把bean的实例传递给bean的后置处理器方法

    • bean可以使用了——对象已经获取到

    • 当容器关闭的时候,调用bean的销毁方法(需要进行配置)
      在这里插入图片描述

  • 后置处理器的实现方法——实现BeanPostProcessor
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Av736gi-1663328880609)(F:\typroa\aimages\image-20220914213848567.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pLsZzObe-1663328880610)(F:\typroa\aimages\image-20220914214205055.png)]

6、引入外部的配置文件

  • 创建一个外部的配置文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pDQu9J8R-1663328880610)(F:\typroa\aimages\image-20220914221338472.png)]

  • 把外部的属性文件引入到spring的配置为文件中,并配置名称空间
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OOaeWcV1-1663328880611)(F:\typroa\aimages\image-20220914221654488.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值