【Spring】 - 基于xml的两种依赖注入方式(构造函数注入,setter注入)

本文介绍了Spring框架下如何进行XML配置的依赖注入,包括通过构造函数注入(单个参数和多个参数的情况)以及setter方法注入的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Spring中依赖注入 dependency injection  (DI)一般来说有两种形式: 1)基于xml的依赖注入, 2)基于注解的依赖注入。
基于xml的依赖注入方式通常又可以分为:1)构造函数方式注入。2)setter方式注入。

环境

Spring4.3.9, JDK1.8  pom添加spring依赖如下:
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.9.RELEASE</version>
</dependency>
一个包就够了。

测试项目结构:
目的:将HelloService的实例HelloServiceImpl注入到HelloPrinter中并在Application中通过容器取出来使用。

代码如下:
HelloService接口
public interface HelloService {
	String sayHello();
}
HelloService实现
public class HelloServiceImpl implements HelloService {

	public String sayHello() {
		return "hello";
	}
	
}

HelloPrinter类(未完成版本,在这里使用不同的方法依赖注入)
public class HelloPrinter {

	private HelloService helloService;
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}
Application类
public class Application {
	
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
		HelloPrinter printer = (HelloPrinter) context.getBean("helloPrinter");
		printer.print();
	}
}

依赖注入

构造函数方式

单个参数

HelloPrinter类:
public class HelloPrinter {

	private HelloService helloService;
	
	public HelloPrinter(HelloService helloService) {
		this.helloService = helloService;
	}
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}
添加了构造函数,同时通过构造函数初始化helloService

spring.xml配置(以下helloService的配置省略):
<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="helloService" class="io.spring.hello.HelloServiceImpl" />
    
    <bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
        <constructor-arg ref="helloService" />
    </bean>

</beans>
首先使用<bean id="xx" class="xxx" />的方式将helloService的实例加入容器。
再使用上面的<constructor-arg>注入
运行输出:
hello


多个参数

1. 按照顺序注入
HelloPrinter类:
public class HelloPrinter {

	private HelloService helloService;
	
	public HelloPrinter(HelloService helloService, String s1, String s2, int id) {
		this.helloService = helloService;
		System.out.println(s1 + s2 + id);
	}
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}

xml配置:
<bean id="helloService" class="io.spring.hello.HelloServiceImpl" />
    
<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <constructor-arg ref="helloService" />
    <constructor-arg value="aaa"/>
    <constructor-arg value="bbb"/>
    <constructor-arg value="123"/>
</bean>
运行输出:
aaabbb123
hello
2. 按照类型注入
HelloPrinter
public class HelloPrinter {

	private HelloService helloService;
	
	public HelloPrinter(HelloService helloService, String s, int id) {
		this.helloService = helloService;
		System.out.println(s + id);
	}
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}

xml配置
<bean id="helloService" class="io.spring.hello.HelloServiceImpl" />

<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <constructor-arg type="int" value="123"/>
    <constructor-arg type="io.spring.hello.HelloService" ref="helloService" />
    <constructor-arg type="java.lang.String" value="aaa"/>
</bean>
即使顺序不同也可以正确注入。
如果有多个相同的类型,则按照实际注入的顺序和构造器中参数类型的顺序决定。(相同的类型先到先得)

运行输出:
aaa123
hello

3. 按照name注入

HelloPrinter
public class HelloPrinter {

	private HelloService helloService;
	
	public HelloPrinter(HelloService helloService, String s, int id) {
		this.helloService = helloService;
		System.out.println(s + id);
	}
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}

xml
<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <constructor-arg name="id" value="123"/>
    <constructor-arg name="helloService" ref="helloService" />
    <constructor-arg name="s" value="aaa"/>
</bean>
指定构造器中参数的name
输出:
aaa123
hello

4. 按照index注入
HelloPrinter
public class HelloPrinter {

	private HelloService helloService;
	
	public HelloPrinter(HelloService helloService, String s, int id) {
		this.helloService = helloService;
		System.out.println(s + id);
	}
	
	public void print() {
		System.out.println(helloService.sayHello());
	}
	
}
xml配置:
<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <constructor-arg index="2" value="123"/>
    <constructor-arg index="0" ref="helloService" />
    <constructor-arg index="1" value="aaa"/>
</bean>
index从0开始,分别对应构造器中的参数顺序。


setter注入

HelloPrinter
public class HelloPrinter {

	private HelloService helloService;
	
	private String s;
	
	private int id;
	
	public void setHelloService(HelloService helloService) {
		this.helloService = helloService;
	}

	public void setS(String s) {
		this.s = s;
	}

	public void setId(int id) {
		this.id = id;
	}

	public void print() {
		System.out.println(helloService.sayHello() + s + id);
	}
	
}

xml配置:

<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <property name="helloService" ref="helloService" />
    <property name="s" value="hhhh" />
    <property name="id" value="123123" />
</bean>
运行输出:
hellohhhh123123


注意:使用构造器注入方式不能出现循环的依赖注入

例:


<bean id="helloService" class="io.spring.hello.HelloServiceImpl">
    <constructor-arg name="helloPrinter" ref="helloPrinter" />
</bean>

<bean id="helloPrinter" class="io.spring.hello.HelloPrinter">
    <constructor-arg name="helloService" ref="helloService" />
</bean>
spring会报错

Error creating bean with name 'helloService': Requested bean is currently in creation: Is there an unresolvable circular reference?



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值