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;
}
}
在不同的配置中,connectionNum 和 databaseName 的值可以根据实际需要进行更改,而不需要修改 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注入(因为很少自己主动写构造函数)。