1.问题思考(1):向一个类中传递数据的方式有几种?
setter方法
构造方法
2.问题思考(2):依赖注入描述了在容器中建立bean与bean之间的依赖关系的过程,如果bean运行需要的是数字或者字符串呢?
引用类型
简单类型(基本数据类型与String)
3.问题思考(3):依赖注入方式有几种?
(1)setter注入
简单类型
引用类型
(2)构造器注入
简单类型
引用类型
setter方法注入
一,多种引用数据类型的情况下,(包含单个引用数据类型的情况下)
1.在bean中定义引用类型属性,并提供可访问的set方法
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.service.BookService;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class BookServiceImpl implements BookService{
private BookDao bookDao;
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void save() {
System.out.println("Service save.....");
}
}
2.在Spring配置文件上使用property标签ref属性注入引用类型对象
<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!--
多个引用类型的形况下
name是service的变量名
ref写已有的bean,也就是上方的bean
-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"></property>
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
二,多种普通数据类型的情况下,(String与Integer)
1.在bean中定义引用类型属性,并提供可访问的set方法
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
private Integer connectionNumber;
private String databaseName;
public void setConnectionNumber(Integer connectionNumber) {
this.connectionNumber = connectionNumber;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public void save() {
System.out.println("bookDao save ..."+connectionNumber+","+databaseName+"");
}
}
2.在Spring配置文件上使用property标签value属性内写入值,Spring会自动识别
<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<property name="databaseName" value="mysql"></property>
<property name="connectionNumber" value="100000"></property>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!--
多个引用类型的形况下
name是service的变量名
ref写已有的bean,也就是上方的bean
-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"></property>
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
构造器注入
一,多种 引用数据类型的情况下,(包含单个引用数据类型的情况下)
1.在bean中定义引用类型属性,并提供可访问的构造方法
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.service.BookService;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private UserDao userDao;
public BookServiceImpl(BookDao bookDao, UserDao userDao) {
this.bookDao = bookDao;
this.userDao = userDao;
}
@Override
public void save() {
System.out.println("Service save.....");
bookDao.save();
userDao.save();
}
}
2.在Spring配置文件上使用constructor-arg标签ref属性注入引用类型对象,Spring会自动识别
<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!--
name指的是构造函数中的形参的名称
ref指的还是上方的bean对象
-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
</beans>
二,多种普通数据类型的情况下,(String与Integer)
1.在bean中定义引用类型属性,并提供可访问的构造方法(dao)
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
private Integer connectionNumber;
private String databaseName;
public BookDaoImpl(Integer connectionNumber, String databaseName) {
this.connectionNumber = connectionNumber;
this.databaseName = databaseName;
}
public void save() {
System.out.println("bookDao save ..."+connectionNumber+","+databaseName+"");
}
}
2.在Spring配置文件上使用constructor-arg标签Value属性给普通数据类型赋值,Spring会自动识别
name指的是构造函数中的形参的名称
ref指的还是上方的bean对象
<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg name="connectionNumber" value="10000"></constructor-arg>
<constructor-arg name="databaseName" value="mysql"></constructor-arg>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!--
name指的是构造函数中的形参的名称
ref指的还是上方的bean对象
-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
</beans>
问题:我们在dao层定义了一个databaseName的基本数据类型进行注入,但是当databaseName更换了名字之后,我们就发现,耦合度太高,以至于我们在配置文件上也得发生改变,所以要进行解耦
构造器注入----参数适配
第一种方式(标准书写)
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg name="connectionNumber" value="10000"></constructor-arg>
<constructor-arg name="databaseName" value="mysql"></constructor-arg>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
第二种方式(按照顺序和数据类型进行参数适配)
解决了形参名称的问题,与形参名称不耦合了
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg type="java.lang.Integer" value="10000"></constructor-arg>
<constructor-arg type="java.lang.String" value="mysql"></constructor-arg>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
第三种方式(按照索引与数据类型进行参数适配)我认为是最好用的
解决参数类型重复问题,使用位置来解决参数的匹配
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg type="java.lang.Integer" index="0" value="10000"></constructor-arg>
<constructor-arg type="java.lang.String" index="1" value="mysql"></constructor-arg>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
依赖注入方式选择
1.强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
2.可选依赖使用setter诸如进行,灵活性强
3.Spring框架倡导使用构造器,第三方框架内部大多数采用构造器的形式进行数据的初始化,相对严谨
4.如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
5.实际开发的过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器开发
6.自己开发的模块,推荐使用setter注入