SpringIoc(控制反转)和DI(依赖注入)详解

Ioc&DI

Ioc控制反转是一种设计思想 ,DI (依赖注入)是实现 IoC 的一种方法,也有人认为 DI 只是 IoC 的另一种说法。没有 IoC 的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。

什么是Ioc

Ioc是指控制程序对象之间的关系、将对象的控制权由程序代码 转换到了外部容器当中。控制权的转移也叫控制反转(Ioc)。对于 Spring 而言,就是由 Spring 来控制对象的生命周期和对象之间的依赖关系。

什么是DI

Ioc 还有另外一个名字——“依赖注入。所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,由容器动态地将某种依赖关系注入到组件之中。

IOC的实现

  1. 引入依赖
<!-- 引入了SpringIOC的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.20</version>
</dependency>

2.加载配置类

3.获得对象

xml实现

对象赋值

常见类型

Setter方法
    <!--SpringIOC的容器,负责管理对象的-->

    <!--
        产生DemoA类的对象
        bean:代表一个对象
            ID:代表的是对象的名字
            class:代表对象是那个类产生的
    -->
    <!--
        DemoA a = new DemoA();
    -->
    <bean class="com.fzj.spring.ioc.xml.DemoA" id="a"/>

    <!--产生对象属性并赋值-->
    <!--Setter-->
    <bean class="com.fzj.spring.ioc.xml.DemoA" id="b">

        <!--给对象属性赋值 Setter方法-->
        <!--
        name:属性名
        value:值
        -->
        <property name="id" value="1"/>
        <property name="name">
            <value>ff</value>
        </property>
        <property name="gender" value=""/>
    </bean>
  
构造器
` <!--一个参数的构造器-->
    <bean class="com.fzj.spring.ioc.xml.DemoA" id="c1">
        <!--
            通过构造器赋值
            constructor-arg:给某个属性赋值
                value:值
                index:第几个参数
                name:参数名(和index作用一致)
        -->
        <constructor-arg value="1" index="0"/>
    </bean>
    <!--两个参数的构造器-->
    <!--
           通过构造器赋值
           constructor-arg:给某个属性赋值
               value:值
               index:第几个参数
               name:参数名(和index作用一致)
     -->
    <bean class="com.fzj.spring.ioc.xml.DemoA" id="c2">
        <constructor-arg value="1" name="id"/>
        <constructor-arg value="张三" index="1"/>
    </bean>
    <!--全参构造器-->
    <bean class="com.fzj.spring.ioc.xml.DemoA" id="c3">
        <constructor-arg name="id" value="1"/>
        <constructor-arg index="1" value="李四"/>
        <constructor-arg name="gender" value=""/>
    </bean>

数组集合类型

Setter方法
<!--setter方式-->
    <bean class="com.fzj.spring.ioc.xml.DemoB" id="b1">

        <property name="array">
            <array>
                <value>陕西</value>
                <value>福建</value>
                <value>广西</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>西安</value>
                <value>宝鸡</value>
                <value>商洛</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>足球</value>
                <value>篮球</value>
                <value>排球</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="A" value="aa"/>
                <entry key="B" value="bb"/>
            </map>
        </property>
    </bean>
构造器
    <!--构造器方式赋值-->
    <bean class="com.fzj.spring.ioc.xml.DemoB" id="b2">
        <constructor-arg index="0">
            <array>
                <value>陕西</value>
                <value>福建</value>
                <value>广西</value>
            </array>
        </constructor-arg>
        <constructor-arg index="1">
            <list>
                <value>西安</value>
                <value>宝鸡</value>
                <value>商洛</value>
            </list>
        </constructor-arg>

        <constructor-arg name="set">
            <set>
                <value>足球</value>
                <value>篮球</value>
                <value>排球</value>
            </set>
        </constructor-arg>
        <constructor-arg name="map">
            <map>
                <entry key="A" value="aa"/>
                <entry key="B" value="bb"/>
            </map>
        </constructor-arg>
    </bean>

对象类型

Setter方法
 <!--给自定义类型属性赋值-->
    <bean class="com.fzj.spring.ioc.xml.DemoC" id="d1">
        <!--通过使用 ref 标记指定 bean 属性的目标 bean-->
        <property name="a" ref="a"/>
        <property name="b" ref="b2"/>
    </bean>

获取对象

byName

通过对象名获取 缺点是返回的类型是Object类型的需要自行强转

  ApplicationContext c = new ClassPathXmlApplicationContext("applicationContext.xml");
  //byName
  Object a = c.getBean("b");
  System.out.println(a);
byType

通过类型自动获取对象 缺点是 当容器中出现多个相同类型的对象时 无法自动匹配

 //byType
 DemoC c1 = c.getBean(DemoC.class);
 System.out.println(c1);
byType+byName

通过类型+名字精准获取对象 缺点是写得多

//byTyp+byName
DemoA a1 = c.getBean("c2", DemoA.class);
 System.out.println(a1);

加载Ioc容器方式

FileSystemXmlApplicationContext 实现方式

这种方式是以项目路径为相对路径的绝对起点 非maven项目

ApplicationContext bean = new FileSystemXmlApplicationContext("ioc/src/main/resources/applicationContext.xml");
ClassPathXmlApplicationContext实现方式

这种方式是以maven的resources 文件夹为相对路径起始点

ApplicationContext bean = new ClassPathXmlApplicationContext("applicationContext.xml");
XmlWebApplicationContext 实现方式

在 Web 环境下初始化监听器的时候会加载。很少使用

AnnotationConfigApplicationContext 实现方式

注解方法 零xml配置。根据注解的方式启动Spring容器

ApplicationContext bean = new AnnotationConfigApplicationContext("com.dailyblue.java.spring");

注解实现

产生对象

名称功能
@Component用于普通类、启动spring后,会自动把它转成容器管理的bean
@Repository用于DAO层注解 功能同@Component
@Service用于对业务层注解 功能同@Component
@Controller用于对控制层注解 功能同@Component

使用时如果没有自定义名字默认是类名首字母小写 使用value属性来自定义属性名

对象赋值

名称功能
@Autowired默认按照类型(byType)自动装配 缺点是当有多个相同类型时会出错
@ResourcebyName(+byType):按照名称赋值,如果名称不存在,按照类型赋值
@Autowired @Qualifier(“a2”)// 辅助@Autowired注解的使用,在byType基础上增加了byName功能
   //赋值注解
    @Autowired       // byType:按照类型自动赋值
    //byType
    private DemoA a;

    @Resource(name = "a2")//将对象名为a2的类赋值给a1
    //byName(+byType)   // byName(+byType):按照名称赋值,如果名称不存在,按照类型赋值
    private DemoA a1;

    @Autowired
    @Qualifier("a2")  // 辅助@Autowired注解的使用,在byType基础上增加了byName功能
    private DemoA a3;

byName和byType区别

byName是根据对象名来注入对象、缺点是返回的类型是Object类型 需要强转

byType是跟据类型来自动注入对象 缺点是无法满足多个相同类型对象的场景 无法自动识别装配

@Autowired和@Resource的区别

相同:都是实现对象赋值的

不同:

@Autowired按照所需类型自动装配的 在出现多个相同类型的对象时 无法自动识别装配

@Resource默认按照名称赋值 如果名称不存在再按照类型赋值

设计模式

单例模式

一个类有一个对象

多例模式

一个类由多个对象

@Component
//设置当前类只产生一个对象(也是默认效果)
//@Scope(value = "singleton")
//每次获取当前类对象时 产生对象
@Scope(value = "prototype")
public class DemoC {

}

配置管理

配置类注解

@Configuration 声明为配置类 在加载资源时会从该类开始

//声明为配置类
@Configuration
public class SpringConfig {
    
}

手动扫描

配置扫描那些包,一次可以扫描多个包

@ComponentScan("com.fzj.spring.ioc.annotation.bean")
//扫描多个包的方式
//@ComponentScan(basePackages = {"com.fzj.spring.ioc.annotation.bean", "com.fzj.spring.ioc.annotation.config"})

手动产生对象并放到Ioc容器中

使用场景 使用别人开发的资源

@Configuration
@ComponentScan("com.fzj.spring.ioc.annotation.bean")
//扫描多个包的方式
//@ComponentScan(basePackages = {"com.fzj.spring.ioc.annotation.bean", "com.fzj.spring.ioc.annotation.config"})
public class SpringConfig {

    //手动添加对象到Ioc容器中
    @Bean
    public DemoE getDemoE() {
        return new DemoE();
    }
}

SpringIoc中bean的生命周期

Bean的生命周期包括 bean的定义、bean的初始化、bean的使用、bean的销毁

Bean 的生命周期包括 Bean 的定义,Bean 的初始化,Bean 的使用,Bean 的销毁。

Bean 的定义:一般 Bean 使用 XML 文件的方式进行定义,定义的时候将 Bean 之间的依赖关系和属性的赋值都进行了定义。

Bean 的初始化:其实 Bean 的初始化包括 Bean 的创建和初始化两个方法,Bean 的创建和初始化一般是同步进行的,Bean 在完成创建后直接就会进行初始化操作,创建的时机与 Bean 的 lazy-init 属性的设置有关。

Bean 的使用:在 web 程序运行期间,发生对某一个 Bean 的调用时,就会使用这个 Bean实例,如果使用编码的方式来获取 Bean 同样也是 Bean 的使用,Bean 的编码使用方式有三种,第一种是使用 BeanWarpper,第二种是使用 BeanFactory,第三种就是使用 ApplicationContext。

Bean 的销毁:Bean 实例在程序退出的时候会进行销毁,而在销毁之前会自动调用 Bean的 destory-method 属性指定名称的方法。

Bean的定义:

xml方式

 <bean class="com.fzj.spring.ioc.xml.DemoA" id="a"/>

注解方式

使用 @Component @Controller @Repository @Service 四种注解添加到类上时

bean的创建和初始化

bean的创建及初始化默认在加载配置文件时

bean的使用

xml方式在使用byName 、byType等时候

注解方式 在使用 @Autowired @Resource

bean的销毁

Bean 实例在程序退出的时候会进行销毁,而在销毁之前会自动调用 Bean的 destory-method 属性指定名称的方法。

IoC管理对象的创建

勤加载

默认情况,当启动IoC容器时,加载创建XML或者注解中的对象。

懒加载

当启动IoC容器时,不创建XML或者注解中的对象。只有在使用时才创建。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值