依赖注入是一种处理对象间依赖关系的技术。在Spring中,依赖注入有构造方法注入和设值注入两种方式。
本次我们将通过具体例子来讲解这两种方式。
果汁店(juiceMaker)通过顾客的信息单(List)来生产饮品。
caseA - 取餐号001 ,橙汁,少糖,大杯
caseB- 取餐号002 ,贡茶,无糖,中杯
<dependencies>
<!--spring context依赖-->
<!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.6</version>
</dependency>
<!--junit5测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
IoC容器在实例化Bean的过程中,会根据Bean的定义中的属性,查找并注入依赖。如果Bean定义中指定了构造函数,IoC容器会调用该构造函数,并将需要的依赖作为参数传递给该构造函数
1,此类的属性,fruit_sort,fruit_sugar,fruit_size。
2,toString方法方便测试。
3,构造方法ListA,上的@ConstructorProperties在测试中解释。
package com.zjr.list;
import java.beans.ConstructorProperties;
/**
* 果汁的信息单
*/
public class ListA {
private String fruit_sort;
private String fruit_sugar;
private String fruit_size;
@Override
public String toString() {
return "ListA{" +
"fruit_sort='" + fruit_sort + '\'' +
", fruit_sugar='" + fruit_sugar + '\'' +
", fruit_size='" + fruit_size + '\'' +
'}';
}
@ConstructorProperties({"fruit_sort","fruit_sugar","fruit_size"})
public ListA(String fruit_sort, String fruit_sugar, String fruit_size){
this.fruit_sort = fruit_sort;
this.fruit_sugar = fruit_sugar;
this.fruit_size = fruit_size;
}
}
1,doWork方便测试
2,构造函数MakerA
package com.zjr.juiceMaker;
import com.zjr.list.ListA;
/**
* 基于构造函数的依赖注入
*/
public class MakerA {
private ListA listA;
public String customNumber;
public MakerA(ListA listA,String customNumber){
this.listA = listA;
this.customNumber = customNumber;
}
public void doWork(){
System.out.println("请"+customNumber+"号顾客取餐 --"+listA.toString());
}
}
<?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">
<!--声明listA为bean-->
<bean id="listA" class="com.zjr.list.ListA">
<constructor-arg name="fruit_sort" value="橙汁"></constructor-arg>
<constructor-arg name="fruit_sugar" value="少糖"></constructor-arg>
<constructor-arg name="fruit_size" value="小杯"></constructor-arg>
</bean>
<!--声明MakerA为bean-->
<bean id="makerA" class="com.zjr.juiceMaker.MakerA">
<constructor-arg name="listA" ref="listA"></constructor-arg>
<constructor-arg name="customNumber" value="001"></constructor-arg>
</bean>
</beans>
在maven工程的测试类中新建一个测试类,写入测试方法如下代码。以下代码采用IOC接口ApplicationContext,实现方法是ClassPathXmlApplicationContext。
import com.zjr.juiceMaker.MakerA;
import com.zjr.juiceMaker.MakerB;
import com.zjr.list.ListA;
import com.zjr.list.ListB;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test_makerA {
/**
* 测试由JuiceA.xml配置的bean是否可以正常使用
* 使用IOC容器接口ApplicationContext 接口实现方法为 类路径配置xml实现
* 从IOC接口的实例化对象中调用bean,getBean(bean的id,bean的类)
*/
@Test
public void testA(){
ApplicationContext context = new ClassPathXmlApplicationContext("JuiceA.xml");
ListA listA = context.getBean("listA",ListA.class);
MakerA makerA = context.getBean("makerA",MakerA.class);
makerA.doWork();
System.out.println("信息--"+listA.toString());
}
}
设值注入是指通过setter方法传入被调用者的实例,从而实现依赖注入的一种方式。这种方式简单、直观,因此在Spring的依赖注入中大量使用。
package com.zjr.list;
public class ListB {
private String fruit_sort;
private String fruit_sugar;
private String fruit_size;
@Override
public String toString() {
return "ListB{" +
"fruit_sort='" + fruit_sort + '\'' +
", fruit_sugar='" + fruit_sugar + '\'' +
", fruit_size='" + fruit_size + '\'' +
'}';
}
//set方法
public void setFruit_sort(String fruit_sort) {
this.fruit_sort = fruit_sort;
}
public void setFruit_sugar(String fruit_sugar) {
this.fruit_sugar = fruit_sugar;
}
public void setFruit_size(String fruit_size) {
this.fruit_size = fruit_size;
}
}
package com.zjr.juiceMaker;
import com.zjr.list.ListB;
/**
* 基于setter方法的依赖注入
*/
public class MakerB {
private ListB listB;
public String customNumber;
public void setListB(ListB listB){
this.listB = listB;
}
public void setCustomNumber(String customNumber){
this.customNumber = customNumber;
}
public void doWork(){
System.out.println("请"+customNumber+"号顾客取餐");
}
}
<?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">
<!--声明listA为bean-->
<bean id="listB" class="com.zjr.list.ListB">
<property name="fruit_sort" value="贡茶"></property>
<property name="fruit_sugar" value="无糖"></property>
<property name="fruit_size" value="中杯"></property>
</bean>
<!--声明MakerB为bean-->
<bean id="makerB" class="com.zjr.juiceMaker.MakerB">
<property name="listB" ref="listB"></property>
<property name="customNumber" value="002"></property>
</bean>
</beans>
测试代码如下所示
import com.zjr.juiceMaker.MakerB;
import com.zjr.list.ListA;
import com.zjr.list.ListB;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testMakerB {
/**
* 测试由JuiceB.xml配置的bean是否可以正常使用
* 使用IOC容器接口ApplicationContext 接口实现方法为 类路径配置xml实现
* 从IOC接口的实例化对象中调用bean,getBean(bean的id,bean的类)
*/
@Test
public void testB(){
ApplicationContext context = new ClassPathXmlApplicationContext("JuiceB.xml");
ListB listB = context.getBean("listB",ListB.class);
MakerB makerB = context.getBean("makerB",MakerB.class);
makerB.doWork();
System.out.println("信息--"+listB.toString());
}
}
本次所举的例子也可以联系三层架构,控制层调用业务层,业务层调用数据层,然后把各层的各个组件配置进IOC容器,并完成DI。欢迎评论区交流。