4. Spring对IoC的实现

2024-06-26 08:32:25 浏览数 (1)

1. IoC 控制反转

对控制反转的理解: 控制反转是一种思想。 控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。 控制反转,反转的是什么?

  • 将对象的创建权利交出去,交给第三方容器负责。(我的理解:也就是不用自己new 对象了 , 交给Spring容器进行处理)
  • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。

控制反转这种思想如何实现呢?

  • DI(Dependency Injection):依赖注入 (控制反转的具体实现)

2. 依赖注入

对依赖注入的理解 依赖注入实现了控制反转的思想。 Spring通过依赖注入的方式来完成Bean管理的。 Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。 依赖注入:

  • 依赖指的是对象和对象之间的关联关系。
  • 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。

依赖注入常见的实现方式包括两种:

  • 第一种:set注入
  • 第二种:构造注入

2.1 set 注入

set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法。

重点内容:

代码语言:javascript复制
<?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">

    <bean id="userDaoBean" class="com.north.spring6.dao.UserDao"/>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    </bean>

</beans>

实现原理 通过property标签获取到属性名:userDao 通过属性名推断出set方法名:setUserDao 通过反射机制调用setUserDao()方法给属性赋值 property标签的name是属性名。 property标签的ref是要注入的bean对象的id。(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:创建系统组件之间关联的动作)

通过测试看到程序仍然可以正常执行,说明property标签的name是:setUserDao()方法名演变得到的。演变的规律是:

  • setUsername() 演变为 username
  • setPassword() 演变为 password
  • setUserDao() 演变为 userDao
  • setUserService() 演变为 userService

另外,对于property标签来说,ref属性也可以采用标签的方式,但使用ref属性是多数的:

代码语言:javascript复制
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
  <property name="userDao">
    <ref bean="userDaoBean"/>
  </property>
</bean>

总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。

2.2 构造注入

核心原理:通过调用构造方法来给属性赋值。

xml 文件配置信息:

代码语言:javascript复制
<?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">

    <bean id="userDaoBean" class="com.north.spring6.dao.UserDao"></bean>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <!--第一种配置方式-->
        <!--<constructor-arg ref="userDaoBean"></constructor-arg>-->
        <!--第二种配置方式-->
        <!--<constructor-arg index="0" ref="userDaoBean"></constructor-arg>-->
        <!--第三种配置方式-->
        <constructor-arg name="userDao" ref="userDaoBean"></constructor-arg>
    </bean>
</beans>

通过测试得知,通过构造方法注入的时候:

  • 可以通过下标
  • 可以通过参数名
  • 也可以不指定下标和参数名,可以类型自动推断

Spring在装配方面做的还是比较健壮的。

3. set 注入专题

3.1 注入外部 bean

外部Bean的特点:bean定义到外面,在property标签中使用ref属性进行注入。通常这种方式是常用。

代码语言:javascript复制
<?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">

    <bean id="userDaoBean" class="com.north.spring6.dao.UserDao"/>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    </bean>

</beans>

3.2 注入内部 bean

内部Bean的方式:在bean标签中嵌套bean标签。

代码语言:javascript复制
<?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">

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao">
            <bean class="com.north.spring6.dao.UserDao"/>
        </property>
    </bean>

</beans>

3.3 注入简单类型

需要特别注意:如果给简单类型赋值,使用value属性或value标签。而不是ref。

通过源码分析得知,简单类型包括:

  • 基本数据类型
  • 基本数据类型对应的包装类
  • String或其他的CharSequence子类
  • Number子类
  • Date子类
  • Enum子类
  • URI
  • URL
  • Temporal子类
  • Locale
  • Class
  • 另外还包括以上简单值类型对应的数组类型。

3.4 级联属性赋值 (了解)

代码语言:javascript复制
<?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">

    <bean id="clazzBean" class="com.north.spring6.beans.Clazz"/>

    <bean id="student" class="com.north.spring6.beans.Student">
        <property name="name" value="张三"/>

        <!--要点1:以下两行配置的顺序不能颠倒-->
        <property name="clazz" ref="clazzBean"/>
        <!--要点2:clazz属性必须有getter方法-->
        <property name="clazz.name" value="高三一班"/>
    </bean>
</beans>

要点:

  • 在spring配置文件中,如上,注意顺序。
  • 在spring配置文件中,clazz属性必须提供getter方法。

3.5 注入数组

3.6 注入List集合

3.7 注入Set集合

3.8 注入Map集合

3.9 注入Properties

3.10 注入null和空字符串

3.11 注入的值中含有特殊符号

4. 基于p命名空间的注入

P命名空间注入:底层实际上还是set​注入 , 用于简化set​注入 , 注意:不能省略set方法

5. 基于c命名空间的注入

基于构造放啊​ , 简化构造注入​ , 注意:不能省略构造方法

6. util 命名空间让配置复用

7. 基于XML的自动装配

7.1 根据名称自动装配

7.2 根据类型自动装配

8. Spring 引入外部属性配置文件

0 人点赞