前言
刚刚学习了 Spring IOC,我们都知道 Spring 框架的实现依赖 IoC 原则,更为形象的称呼是 DI (dependency injection,依赖注入)。
DI 有三种方式:
- Constructor
- Setter
- 注解
先记录一下传统的项目结构,然后引出 IoC 记录一下使用 Setter 配置 xml 的依赖注入。
传统方式
传统方式下,service 层调用 dao层,测试类里必须要实例化 service 层,ServiceImpl 实例化 dao 层,这样才能实现访问数据库。
// Test 测试类:
// 传统方式使用 UserServiceImpl 实例化
private IUserService userService = new UserServiceImpl();
// UserServiceImpl
private IUserDao userDao = new UserDaoImpl();
那么问题来了,如果下层还没有完工,我们就没法加快上层进度,于是便有了依赖注入:利用 Bean 构造依赖的对象。
一、Setter 注入 Bean
项目结构:
1、IUserDao 接口
package com.zjy.ioctest1.dao;
public interface IUserDao {
public void sayHello();
}
2、UserDaoImpl 实现类
package com.zjy.ioctest1.dao.impl;
import com.zjy.ioctest1.dao.IUserDao;
public class UserDaoImpl implements IUserDao {
@Override
public void sayHello() {
System.out.println("dao 层被调用!");
}
}
3、IUserService 接口
package com.zjy.ioctest1.service;
public interface IUserService {
public void sayHello();
}
4、UserServiceImpl 实现类
package com.zjy.ioctest1.service.impl;
import com.zjy.ioctest1.dao.IUserDao;
import com.zjy.ioctest1.service.IUserService;
public class UserServiceImpl implements IUserService {
private IUserDao userDao;
// 这里不能使用 ac.getBean() 实例化
// public UserServiceImpl() {
// System.out.println("service 的构造函数已被调用!");
// } 可以输出 说明在test里对userService进行了无参构造
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void sayHello() {
System.out.println("service 层被调用!");
userDao.sayHello();
}
}
5、Bean.xml 配置
需要注意的是,要在 xml 中指明依赖之间的关系,因为 userService 还要依赖 userDao,所以要注意 < property > 标签。
<?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="com.zjy.ioctest1.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.zjy.ioctest1.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<!-- 在XML中通过 <property name="userDao" ref="userDao"/>指明依赖关系。-->
</beans>
6、测试类中 Setter 注入 Bean
package com.zjy.ioctest1;
import com.zjy.ioctest1.service.IUserService;
import com.zjy.ioctest1.service.impl.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SpringBootTest
class Ioctest1ApplicationTests {
// 传统方式使用 UserServiceImpl 实例化
// private IUserService userService = new UserServiceImpl();
private IUserService userService;
// 这种方式将会使用spring容器注入
@Test
void contextLoads() {
}
@Test
public void testHello() {
// 告诉Test程序 xml配置文件的位置
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 进行实例化 getBean:使用userService实例化对象
userService = (IUserService) ac.getBean("userService");
userService.sayHello();
}
}
可以看到,Service 层和 UserDao 层都被调用,setter 方法使用成功。
二、Setter 注入字面量
项目结构:
1、Person 实体类
package com.zjy.ioctest02.entity;
public class Person {
private String name;
private String sex;
private int age;
private String hobby;
// 必须有setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
2、Bean.xml 配置
<?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="person" class="com.zjy.ioctest02.entity.Person">
<property name="name" value="jayepep"/>
<property name="sex" value="男"/>
<property name="age" value="18"/>
<property name="hobby" value="Jave EE"/>
</bean>
<!-- 在这里为person的参数赋值 -->
</beans>
3、测试类中 Setter 注入字面量
package com.zjy.ioctest02;
import com.zjy.ioctest02.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SpringBootTest
class Ioctest02ApplicationTests {
@Test
void contextLoads() {
}
// setter注入字面量测试
@Test
void testLiteralSetter() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
Person person = (Person)ac.getBean("person");
System.out.println("姓名: " + person.getName() +
" 性别: " + person.getSex() +
" 年龄: " + person.getAge() +
" 爱好: " + person.getHobby());
}
}
测试成功结果:
三、Setter 注入集合类
setter方法还可以用来注入集合,直接看看实例。
项目结构
1、创建集合类
package com.zjy.ioctest03.entity;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Collection {
private Set<String> set;
private List<String> list;
private Map<String, String> map;
private String[] array;
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
@Override
public String toString() {
return "Collection{" +
"set=" + set + "\n" +
", list=" + list + "\n" +
", map=" + map + "\n" +
", array=" + Arrays.toString(array) + "\n" +
'}';
}
}
2、Bean.xml 配置
<?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">
<!-- setter 方式注入集合-->
<bean id="collection" class="com.zjy.ioctest03.entity.Collection">
<!-- setter 集合的属性注入 -->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
</set>
</property>
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"></entry>
<entry key="key2" value="value2"></entry>
<entry key="key3" value="value3"></entry>
</map>
</property>
<property name="array">
<list>
<value>array1</value>
<value>array2</value>
<value>array3</value>
</list>
</property>
</bean>
</beans>
3、测试类中 Setter 注入集合
package com.zjy.ioctest03;
import com.zjy.ioctest03.entity.Collection;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SpringBootTest
class Ioctest03ApplicationTests {
@Test
void contextLoads() {
}
@Test
public void testListSetter() {
// 根据spring配置文件创建应用上下文
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 从容器中获取bean
Collection collection = (Collection)ac.getBean("collection");
System.out.println("Setter注入集合:" + collection.toString());
}
}
测试成功结果:
四、总结
Spring setter 注入可用于注入bean、字面量、集合,我相信经过以上三个实践以及自己的搜索学习,对 setter 注入的认识一定会更加深刻,为我们以后的上层建筑添砖Java。
说在最后的话:编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~