Spring的IoC和DI

本文深入探讨了控制反转(IoC)和依赖注入(DI)的概念,解释了它们如何降低代码耦合度,以及在Spring框架中如何通过配置文件和不同方式创建与管理Bean对象,包括构造函数注入、set方法注入及注解注入。

基本概念

来自百度百科的解释:

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--把对象的创建交给spring管理-->
    <bean id="accountService" class="com.sx.service.impl.AccountImpl"></bean>
    <bean id="accountDao" class="com.sx.dao.impl.AccountDaoImpl"></bean>
</beans>

ApplicationContext的三个实现类以及和BeanFactory的区别

public class Client {
    /**
     * 获取springIoc的核心容器
     * 根据id获取对象
     * <p>
     * ApplicationContext的三个常用实现类
     *       ClassPathXmlApplicationContext:加载类路径下的配置文件,要求文件必须配置在类路径下。
     *       FileSystemXmlApplicationContext:可以加载磁盘任意路径下的配置文件(必须要有访问权限)。
     *       AnnotationConfigApplicationContext:用于读取注解创建容器。
     * <p>
     * ApplicationContext:      单例对象适用
     *      创建核心容器时才用的策略是立即加载的方式,一读取完配置文件马上创建配置文件中的对象
     * BeanFactory:      多例对象适用
     *      创建核心容器时才用的策略是延时加载的方式,什么时候根据id获取对象,什么时候才真正创建对象
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        //1.获取核心容器
        //ApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\Users\\Admin\\IdeaProjects\\spring01\\src\\main\\resources\\bean.xml");

        //2.根据id获取Bean对象
        //2.1 方式1
        IAccountService accountService = (IAccountService) ac.getBean("accountService");
        //2.2方式2
        IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class);


        System.out.println(accountService);
        System.out.println(accountDao);
        //accountService.saveAccount();
    }
}

创建Bean的三种方式

第一种方式:
<!-- 使用默认构造函数创建。
           在Spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
           采用的就是默认构造方法创建bean对象,此时如果类中没有默认构造方法,则对象无法创建。
   <bean id="accountService" class="com.sx.service.impl.AccountServiceImpl"></bean>
-->
第二种方式:
/**
 * 模拟一个工厂类(该类是存在于jar包中的,无法通过修改源码的方式来提供默认构造函数)
 */
public class InstanceFactory {
    public IAccountService getAccountService() {
        return new AccountServiceImpl();
    }
}

 <!-- 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
    <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
 -->
第三种方式:
/**
 * 模拟一个静态工厂类
 */
public class StaticFactory {
    public static IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

<!--使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
    <bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
 -->

bean的作用范围调整

<!-- bean标签的scope属性:
    	作用:用于指定bean的作用范围
        取值: 常用的就是单例的和多例的
           singleton:单例的(默认值)
           prototype:多例的
           request:作用于web应用的请求范围
           session:作用于web应用的会话范围
           global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
-->

bean对象的生命周期

<!--
	 单例对象:单例对象的生命周期和容器相同。
     多例对象:
         出生:使用对象时Spring框架为我们创建
         存活:对象只要是在使用过程中就一直存活
         死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
 -->

依赖注入

<!--依赖关系的维护就称之为依赖注入。
    能注入的三类数据:
       基本类型和String
       其他bean类型(在配置文件中或者注解配置过的bean)
       复杂类型/集合类型
    注入的方式:有三种
       第一种:使用构造函数提供
       第二种:使用set方法提供
       第三种:使用注解提供
 -->
构造方法注入:
使用的标签:<constructor-arg></constructor-arg>
标签出现的位置:bean标签的内部
标签中的属性
     type:用于指定要注入的数据的数据类型,该数据类型是构造方法中某个或某些参数的类型
     index:用于指定要注入的数据给构造方法中指定索引位置的参数赋值。索引的位置是从0开始
     name:用于指定给构造函数中指定名称的参数赋值 (常用)                                       
     value:用于提供基本类型和String类型的数据
     ref:用于指定其他的bean类型数据。指的就是在Spring的IoC核心容器中出现过的bean对象

     优势:
        在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
     弊端:
        改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。

<bean id="accountService" class="com.sx.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="test"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>

<!-- 配置一个日期对象 -->
<bean id="now" class="java.util.Date"></bean>
set方法注入
使用的标签:property
出现的位置:bean标签的内部
标签的属性
     name:用于指定注入时所调用的set方法名称
     value:用于提供基本类型和String类型的数据
     ref:用于指定其他的bean类型数据。它指的就是在Spring的IoC核心容器中出现过的bean对象
     
     优势:
        创建对象时没有明确的限制,可以直接使用默认构造函数
     弊端:
        如果有某个成员必须有值,则获取对象是有可能set方法没有执行。



<bean id="accountService2" class="com.sx.service.impl.AccountServiceImpl2">
    <property name="name" value="TEST" ></property>
    <property name="age" value="21"></property>
    <property name="birthday" ref="now"></property>
</bean>
复杂类型的注入/集合类型的注入
用于给List结构集合注入的标签:
    list array set
用于个Map结构集合注入的标签:
    map  props
结构相同,标签可以互换

<bean id="accountService3" class="com.sx.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">
      <list>
           <value>AAA</value>
           <value>BBB</value>
           <value>CCC</value>
      </list>
    </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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值