一、本课目标
- 理解构造注入(重点)
- 掌握使用p命名空间实现属性注入(重点)
- 理解不同数据类型的注入方法
二、构造注入
构造注入和之前学习的设值注入都是我们SpringIOC的依赖注入的实现方式。
需求:如何通过构造注入为业务类注入所依赖的数据访问层对象,实现保存用户数据的功能?
分析:
第二步:创建带参构造方法(添加一个无参构造方法)
第三步:在Spring配置文件中通过<constructor-arg>元素为构造方法传参
2.1示例代码:
User实体类:
package entity;
/**
* 用户实体类
*/
public class User implements java.io.Serializable {
private Integer id; // 用户ID
private String username; // 用户名
private String password; // 密码
private String email; // 电子邮件
// getter & setter
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
dao层接口:
package dao;
import entity.User;
/**
* 增加DAO接口,定义了所需的持久化方法
*/
public interface UserDao {
public void save(User user);
}
dao层实现类:
package dao.impl;
import dao.UserDao;
import entity.User;
/**
* 用户DAO类,实现IDao接口,负责User类的持久化操作
*/
public class UserDaoImpl implements UserDao {
public void save(User user) {
// 这里并未实现完整的数据库操作,仅为说明问题
System.out.println("保存用户信息到数据库");
}
}
service层接口:
package service;
import entity.User;
/**
* 用户业务接口,定义了所需的业务方法
*/
public interface UserService {
public void addNewUser(User user);
}
service层实现类:
package service.impl;
import service.UserService;
import dao.UserDao;
import entity.User;
/**
* 用户业务类,实现对User功能的业务管理
*/
public class UserServiceImpl implements UserService {
// 声明接口类型的引用,和具体实现类解耦合
private UserDao dao;
/*// dao 属性的setter访问器,会被Spring调用,实现设值注入
public void setDao(UserDao dao) {
this.dao = dao;
}*/
// 有参构造
public UserServiceImpl(UserDao dao) {
this.dao = dao;
}
// 无参构造
public UserServiceImpl() {
}
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
}
}
配置文件:
<?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="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<!-- 通过constructor-arg元素为构造方法里面的参数赋值 -->
<constructor-arg>
<ref bean="userDao"/>
</constructor-arg>
</bean>
</beans>
测试类代码:
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import entity.User;
import service.UserService;
public class AopTest {
@Test
public void test() {
ApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
User user = new User();
user.setId(1);
user.setUsername("test");
user.setPassword("123456");
user.setEmail("test.@163.com");
userService.addNewUser(user);
}
}
运行结果:
2.2index属性
修改service层实现类:
package service.impl;
import service.UserService;
import dao.UserDao;
import entity.User;
/**
* 用户业务类,实现对User功能的业务管理
*/
public class UserServiceImpl implements UserService {
// 声明接口类型的引用,和具体实现类解耦合
private UserDao dao;
private String s1;
private String s2;
/*// dao 属性的setter访问器,会被Spring调用,实现设值注入
public void setDao(UserDao dao) {
this.dao = dao;
}*/
// 有参构造
public UserServiceImpl(UserDao dao,
String s1) {
this.dao = dao;
this.s1 = s1;
}
// 有参构造
public UserServiceImpl(String s2,UserDao dao) {
this.dao = dao;
this.s2 = s2;
}
// 为dao赋值的有参的构造方法
public UserServiceImpl(UserDao dao) {
this.dao = dao;
}
// 无参构造
public UserServiceImpl() {
}
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
System.out.println("s1 = " + s1);
System.out.println("s2 = " + s2);
}
}
配置文件修改为:
<?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="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<!-- 通过constructor-arg元素为构造方法里面的参数赋值 -->
<constructor-arg>
<ref bean="userDao"/>
</constructor-arg>
<constructor-arg index="1">
<value>123</value>
</constructor-arg>
</bean>
</beans>
运行结果:
注:当有多个构造方法的时候,并且这些构造方法只是参数顺序不同而参数类型相同的时候,可以在配置文件中指定给其赋值的参数的位置。比如在上面的例子中,把index属性值设置为1的时候,就是给
public UserServiceImpl(UserDao dao,
String s1) {
this.dao = dao;
this.s1 = s1;
}
这个构造方法赋值。
这就是constructor-arg标签只是表示构造方法的一个参数,使用时不区分顺序,但是可以使用该元素的index属性指定该参数的位置索引,位置从0开始。
2.3type属性
修改service层实现类:
package service.impl;
import service.UserService;
import dao.UserDao;
import entity.User;
/**
* 用户业务类,实现对User功能的业务管理
*/
public class UserServiceImpl implements UserService {
// 声明接口类型的引用,和具体实现类解耦合
private UserDao dao;
private String s1;
private String s2;
private int i1;
/*// dao 属性的setter访问器,会被Spring调用,实现设值注入
public void setDao(UserDao dao) {
this.dao = dao;
}*/
// 有参构造
public UserServiceImpl(UserDao dao,
String s1) {
this.dao = dao;
this.s1 = s1;
}
// 有参构造
public UserServiceImpl(String s2,UserDao dao) {
this.dao = dao;
this.s2 = s2;
}
// 为dao赋值的有参的构造方法
public UserServiceImpl(UserDao dao) {
this.dao = dao;
}
// 有参构造
public UserServiceImpl(UserDao dao, int i1) {
this.dao = dao;
this.i1 = i1;
}
// 无参构造
public UserServiceImpl() {
}
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
System.out.println("s1 = " + s1);
System.out.println("s2 = " + s2);
System.out.println("i1 = " + i1);
}
}
配置文件:
<?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="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<!-- 通过constructor-arg元素为构造方法里面的参数赋值 -->
<constructor-arg>
<ref bean="userDao"/>
</constructor-arg>
<constructor-arg type="int" index="1">
<value>123</value>
</constructor-arg>
</bean>
</beans>
运行结果:
注:当s1和i1都在构造方法的第二个位置的时候,我在构造注入参数的时候如何保证我赋值的是s1而不是i1或者是i1而不是s1?这时候可以使用constructor-arg标签的type属性指定要赋值的参数的数据类型。
2.4、设值注入与构造注入
在实际开发之中,使用的比较多的还是设值注入。
构造注入在使用的时候,配置文件的参数值设置要跟类里面的构造方法的参数匹配。
三、使用p命名空间注入属性值
p命名空间是针对设置注入的!!!在使用前必须在配置文件中引入p命名空间
实体类代码:
package entity;
/**
* 用户实体类
*/
public class User implements java.io.Serializable {
private Integer id; // 用户ID
private String username; // 用户名
private int age; // 年龄
private String email; // 电子邮件
// getter & setter
public Integer getId() {
return id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
dao层:
package dao;
import entity.User;
/**
* 增加DAO接口,定义了所需的持久化方法
*/
public interface UserDao {
public void save(User user);
}
dao层实现类:
package dao.impl;
import dao.UserDao;
import entity.User;
/**
* 用户DAO类,实现IDao接口,负责User类的持久化操作
*/
public class UserDaoImpl implements UserDao {
public void save(User user) {
// 这里并未实现完整的数据库操作,仅为说明问题
System.out.println("保存用户信息到数据库");
System.out.println("已配置的用户信息如下");
System.out.println("\t用户名为:" + user.getUsername());
System.out.println("\t用户年龄为:" + user.getAge());
System.out.println("\t用户邮箱为:" + user.getEmail());
}
}
service层:
package service;
import entity.User;
/**
* 用户业务接口,定义了所需的业务方法
*/
public interface UserService {
public void addNewUser(User user);
}
service层实现类:
package service.impl;
import service.UserService;
import dao.UserDao;
import entity.User;
/**
* 用户业务类,实现对User功能的业务管理
*/
public class UserServiceImpl implements UserService {
// 声明接口类型的引用,和具体实现类解耦合
private UserDao dao;
public void setDao(UserDao dao) {
this.dao = dao;
}
public void addNewUser(User user) {
// 调用用户DAO的方法保存用户信息
dao.save(user);
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="entity.User" p:username="张三" p:age="20" p:email="test@163.com"></bean>
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl"
p:dao-ref="userDao">
</bean>
</beans>
测试类:
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import entity.User;
import service.UserService;
public class AopTest {
@Test
public void test() {
ApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
User user = (User) context.getBean("user");
userService.addNewUser(user);
}
}
运行结果:
注:p命名空间是跟设值注入绑定的,纯粹是为了简化配置文件。在使用的时候需要先引入p命名空间。