【Spring】05:依赖注入:setter/构造器注入(经典白雪)

120 阅读2分钟

DI,就是bean之间依赖关系的建立!

01:setter 注入(set方法 + property标签)

01-1:引用类型(对象 等)

例:service注入dao对象

property标签:设置注入属性

  • name属性:设置注入的属性名,实际是set方法对应的名称
  • ref属性:设置注入引用类型bean的id或name
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <property name="bookDao" ref="bookDao"/>
    <property name="userDao" ref="userDao"/>
</bean>
//BookServiceImpl
public class BookServiceImpl implements BookService{
    private BookDao bookDao;
    private UserDao userDao;
    //setter注入需要提供要注入对象的set方法
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    //setter注入需要提供要注入对象的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

01-2:简单类型(int 等)

例:service的成员变量

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <!--property标签:设置注入属性-->
    <!--name属性:设置注入的属性名,实际是set方法对应的名称-->
    <!--value属性:设置注入简单类型数据值-->
    <property name="connectionNum" value="100"/>
    <property name="databaseName" value="mysql"/>
</bean>
public class BookDaoImpl implements BookDao {

    private String databaseName;
    private int connectionNum;

    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
}

在不同的配置中,connectionNumdatabaseName 的值可以根据实际需要进行更改,而不需要修改 Java 代码,这就是依赖注入的灵活之处。这样,当需要连接不同数据库或者调整连接数量时,只需要调整配置文件,而不需要重新编译和部署代码

02:构造器注入(构造方法传入 + 属性constructor-arg)

02-1:标准

其中,name指形参,即:public BookServiceImpl(BookDao bookDao, UserDao userDao)里的参数名。

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg name="connectionNum" value="10"/>
    <constructor-arg name="databaseName" value="mysql"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <constructor-arg name="userDao" ref="userDao"/>
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>

service注入dao:

//BookServiceImpl
public class BookServiceImpl implements BookService{
    private BookDao bookDao;
    private UserDao userDao;

    public BookServiceImpl(BookDao bookDao, UserDao userDao) {
        this.bookDao = bookDao;
        this.userDao = userDao;
    }
}

dao注入基本类型:

//BookDaoImpl
public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;

    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
    }
}

02-2:解决形参名称的问题,与形参名不耦合(了解)

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    根据构造方法参数类型注入
    <constructor-arg type="int" value="10"/>
    <constructor-arg type="java.lang.String" value="mysql"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <constructor-arg name="userDao" ref="userDao"/>
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>-->

02-3:解决参数类型重复问题,使用位置解决参数匹配(了解)

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <!--根据构造方法参数位置注入-->
    <constructor-arg index="0" value="mysql"/>
    <constructor-arg index="1" value="100"/>
</bean>

“setter注入”/“构造器注入” 总结

  • 强制依赖:(必须有的东西)使用“构造器注入”(因为如果没有则对象都创建不了报错),而setter注入有概率不进行注入,导致null对象出现。
  • 可选依赖:使用“setter注入”,灵活性更强。
  • Spring 框架倡导使用构造器注入,相对严谨。
  • 自己开发的模块推荐使用setter注入(因为很少自己主动写构造函数)。