Spring DI的理解和实现方式

发布时间:2024年01月13日

Spring DI

名词解释:依赖注入,是对IOC概念的不同角度的描述,是指应用程序在运行时, 每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean 对象。(例如在MyBatis整合Spring时,SqlSessionFactoryBean 依赖IOC容器注入一个 DataSource数据源bean)

Spring DI的实现方法:

  1. 构造注入(通过构造方法进行粘合 )
    <!--===================构造注入(基本类型与String)=========================-->
        <bean id="student" class="com.apesource.common.Student">
            <!--di步骤二-->
            <constructor-arg name="sname" value="王国祥"></constructor-arg>
            <constructor-arg name="sage" value="21"></constructor-arg>
        </bean>
    <!--===================构造注入(javaBean)=========================-->
        <bean id="controllerImp" class="com.apesource.controller.UserControllerImp">
            <constructor-arg name="service" ref="serviceImp"></constructor-arg>
        </bean>
    
        <bean id="serviceImp" class="com.apesource.service.UserServiceImp">
            <constructor-arg name="dao" ref="daoImp"></constructor-arg>
        </bean>
    
        <bean id="daoImp" class="com.apesource.dao.UserDaoImp"></bean>

  2. set注入(通过set方法进行粘合)
    <!--===================set注入(基本类型与String)=========================-->
        <bean id="student" class="com.apesource.common.Student">
            <property name="sname" value="牛牛"></property>
            <property name="sage" value="18"></property>
        </bean>
    <!--===================set注入(javaBean)=========================-->
        <bean id="controllerImp" class="com.apesource.controller.UserControllerImp">
            <property name="service" ref="serviceImp"></property>
        </bean>
    
        <bean id="serviceImp" class="com.apesource.service.UserServiceImp">
            <property name="dao" ref="daoImp"></property>
        </bean>
    
        <bean id="daoImp" class="com.apesource.dao.UserDaoImp"></bean>
    <!--===================set注入(复杂类型)=========================-->
        <bean id="teacher" class="com.apesource.common.Teacher">
            <property name="mylist">
                <list>
                    <value>米饭</value>
                    <value>面条</value>
                    <value>香锅</value>
                    <value>冒菜</value>
                    <value>烧烤</value>
                </list>
            </property>
            <property name="myset">
                <set>
                    <value>唱</value>
                    <value>跳</value>
                    <value>rap</value>
                    <value>篮球</value>
                </set>
            </property>
            <property name="myarray">
                <array>
                    <value>山西</value>
                    <value>河北</value>
                    <value>山东</value>
                    <value>河南</value>
                </array>
            </property>
            <property name="mymap">
                <map>
                    <entry key="中国" value="北京"></entry>
                    <entry key="美国" value="华盛顿"></entry>
                    <entry key="俄罗斯" value="莫斯科"></entry>
                </map>
            </property>
            <property name="prop">
                <props>
                    <prop key="牛逼">10000</prop>
                    <prop key="vsus">10000</prop>
                </props>
            </property>
        </bean>

  3. 属性注入(属性注入不推荐)

    不推荐使用属性注入(即直接在属性上使用 `@Autowired` 注解)主要有以下几个原因:

    1. 封装性破坏:属性注入通常涉及将类成员设置为非私有(通常是包级私有),这违反了封装原则。相比之下,构造注入或者set注入允许保持字段的私有性。

    2. 隐式依赖:属性注入导致依赖关系不够明显。使用构造注入时,所有必需的依赖项都会在创建对象时显式提供,这使得依赖关系更加清晰。

    3. 测试困难:属性注入可能使单元测试变得更加困难,因为没有简单的方法在不启动整个 Spring 上下文的情况下注入依赖。而构造器注入使得在测试时通过构造器手动注入依赖变得容易。

    4. 不可变性和线程安全:通过构造注入,可以将依赖项声明为 `final`,这意味着一旦对象被创建,这些依赖项就不能被更改。这有助于创建不可变和线程安全的对象。

    5. 顺序和优先级问题:使用属性注入时,Spring 容器必须先实例化类,然后才能注入依赖项。在某些情况下,这可能导致依赖项的注入顺序问题。

    总而言之,尽管属性注入在某些情况下看起来更方便快捷,但构造注入或者set注入提供了更好的封装性、更清晰的依赖关系、更容易的测试以及更好的不可变性和线程安全性。因此,在实践中,建议优先考虑使用构造注入或set注入。

DI数据类型:
  1. 注入基本类型与String
  2. 注入JavaBean
  3. 注入复杂类型(构造注入不支持)
DI实现步骤:

1.思考,用什么方式?注入什么数据?

2.提供对应(构造,set)方法

           public Student(String  sname, int sage) {
                this .sname = sname;
                this .sage = sage;
            }

3.配置

<constructor-arg 属性名="属性值"></constructor-arg>

属性名:

name=======>参数名

index======>参数索引

type=======>参数类型

value======>参数具体数据

ref========>参数数据的引用

文章来源:https://blog.csdn.net/2302_78070106/article/details/135510815
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。