文档章节

Spring4-容器4-依赖注入

王胜_淡如止水
 王胜_淡如止水
发布于 2017/03/24 15:32
字数 1229
阅读 13
收藏 1

    依赖注入有两种方式:构造器注入和Setter注入。

1 构造器注入

1.1 构造器参数解析

1.1.1 按照定义顺序解析

    如果构造器参数的类型定义没有潜在的歧义,那么构造器会按照bean定义中构造器参数的定义顺序依次进行匹配。看下面的代码:

package x.y;

public class Foo {

    public Foo(Bar bar, Baz baz) {
        // ...
    }

}

    上述代码中参数类型定义不存在潜在的歧义,我们假设BarBaz之间不存在继承关系。因此,下面代码中在元素<constructor-arg/>的配置即使没有明确指定构造参数顺序或者类型也会起作用。

<beans>
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
    </bean>

    <bean id="bar" class="x.y.Bar"/>

    <bean id="baz" class="x.y.Baz"/>
</beans>

1.1.2 使用type属性来显式指定构造参数类型

    当我们使用简单类型,比如<value>true</value>。Spring并不能知道该值的类型,不借助其他帮助Spring将不能通过类型进行匹配。看下面的类:

package examples;

public class ExampleBean {

    // Number of years to calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}

    针对上面的场景可以使用type属性来显式指定那些简单类型那个的构造参数类型,比如:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

1.1.3 使用index属性来显式指定构造参数的索引

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

    使用索引可以解决多个简单值的混淆,还能解决构造方法有两个相同类型的参数的混淆问题,注意index是从0开始的

1.1.4 使用构造器参数命名来指定值的类型

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

    请记住为了使这个起作用,你的代码编译时要打开编译模式,这样Spring可以检查构造方法的参数。如果你不打开调试模式(或者不想打开),也可以使用@ConstructorProperties JDK注解明确指出构造函数的参数。下面是简单的例子:

package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}

1.2 代码示例

1.2.1 准备Bean类

package com.ws.edu.spring;

public class Food {

}
package com.ws.edu.spring;

public class Game {

}
package com.ws.edu.spring;

public class Person {
	private int id;
	private String name;
	private Food food;
	private Game game;
	
	public Person() {
		super();
	}
	
	public Person(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
	public Person(Food food, Game game) {
		super();
		this.food = food;
		this.game = game;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Food getFood() {
		return food;
	}
	public void setFood(Food food) {
		this.food = food;
	}
	public Game getGame() {
		return game;
	}
	public void setGame(Game game) {
		this.game = game;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", food=" + food
				+ ", game=" + game + "]";
	}
}

1.2.2 配置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="food" class="com.ws.edu.spring.Food"/>
	<bean id="game" class="com.ws.edu.spring.Game"/>
	<!-- 按照定义顺序解析 -->
	<bean id="person1" class="com.ws.edu.spring.Person">
		<constructor-arg ref="food"/>
		<constructor-arg ref="game"/>
	</bean>
	<!-- 使用type属性来显式指定构造参数类型 -->
	<bean id="person2" class="com.ws.edu.spring.Person">
		<constructor-arg type="int" value="2"/>
		<constructor-arg type="java.lang.String" value="小明"/>
	</bean>
	<!-- 使用index属性来显式指定构造参数的索引  -->
	<bean id="person3" class="com.ws.edu.spring.Person">
		<constructor-arg index="0" value="3"/>
		<constructor-arg index="1" value="小明"/>
	</bean>
	<!-- 使用构造器参数命名来指定值的类型 -->
	<bean id="person4" class="com.ws.edu.spring.Person">
		<constructor-arg name="id" value="4"/>
		<constructor-arg name="name" value="小明"/>
	</bean>
</beans>

1.2.3 编写启动类

package com.ws.edu.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;


public class App {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		System.out.println(context.getBean("person1",Person.class));
		System.out.println(context.getBean("person2",Person.class));
		System.out.println(context.getBean("person3",Person.class));
		System.out.println(context.getBean("person4",Person.class));
	}
}

1.2.4 运行结果

2 Setter注入

    示例如下:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

循环依赖

    如果你主要使用构造器注入,很有可能会产生无法解决的循环依赖问题。 举个例子:A类需要通过构造器注入B类的实例,并且B类又需要通过构造器注入A类的实例。如果为类A和类B配置的bean被相互注入的话,Spring IoC容器在运行时会检测到这个循环依赖并且抛出一个BeanCurrentlyInCreationException异常。

    一个可能的解决方法是修改类的源代码,将构造器注入改为setter注入。或者只使用setter注入避免使用构造器注入。换句话说,虽然这并不被推荐使用,你可以使用setter注入配置循环依赖。 和通常的情况不同(没有循环依赖),bean A 和bean B之间的循环依赖将会导致其中一个bean在被完全初始化的之前被注入到另一个bean里(先有鸡先有蛋的问题)

 

 

 

© 著作权归作者所有

王胜_淡如止水
粉丝 4
博文 52
码字总数 81235
作品 0
杭州
私信 提问
Spring4新特性——泛型限定式依赖注入

Spring4新特性——泛型限定式依赖注入 Spring4新特性——核心容器的其他改进 Spring4新特性——Web开发的增强 Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC Spring4新特性...

Big_BoBo
2013/12/26
449
0
Spring的设计理念和设计模式分析

Spring的骨骼架构 Spring中最关键的是Bean组件,可以说spring就是面向bean编程的。spring的流行得益于spring解决了一个关键的问题,让对象之间的依赖关系转而用配置文件来管理,也就是它的注...

Aeroever
02/25
13
0
spring核心框架体系结构

在普通java工程使用spring框架,需要哪些jar呢?只要一个: 那要在web工程中引入spring mvc呢?也只要配置一个依赖: 为什么可以这样配置?接下来我们以spring 3.2.17.RELEASE版本为例,介绍...

心梦无双
2016/12/24
98
0
SSH框架之Spring4专题2:Spring与loC

控制反转(loC,Inversion of Control),是一个概念,是一种思想。指的是将传统上由程序代码直接操纵的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转...

糖醋白糖
2018/06/26
0
0
spring核心框架体系结构

很多人都在用spring开发java项目,但是配置maven依赖的时候并不能明确要配置哪些spring的jar,经常是胡乱添加一堆,编译或运行报错就继续配置jar依赖,导致spring依赖混乱,甚至下一次创建相...

haoran_10
2016/12/22
41
0

没有更多内容

加载失败,请刷新页面

加载更多

JMM内存模型(一)&volatile关键字的可见性

在说这个之前,我想先说一下计算机的内存模型: CPU在执行的时候,肯定要有数据,而数据在内存中放着呢,这里的内存就是计算机的物理内存,刚开始还好,但是随着技术的发展,CPU处理的速度越...

走向人生巅峰的大路
17分钟前
36
0
你对AJAX认知有多少(2)?

接着昨日内容,我们几天继续探讨ajax的相关知识点 提到ajax下面几个问题又是必须要了解的啦~~~ 8、在浏览器端如何得到服务器端响应的XML数据。 通过XMLHttpRequest对象的responseXMl属性 9、 ...

理性思考
26分钟前
4
0
正则表达式基础(一)

1.转义 转义的作用: 当某个字符在表达式中具有特殊含义,例如字符串引号中出现了引号,为了可以使用这些字符本身,而不是使用其在表达式中的特殊含义,则需要通过转义符“\”来构建该字符转...

清自以敬
29分钟前
4
0
idea中@Data标签getset不起作用

背景:换电脑以后在idea中有@data注解都不生效 解决办法:idea装个插件 https://blog.csdn.net/seapeak007/article/details/72911529...

栾小糖
35分钟前
4
0
Apache Kudu 不能删除不存在的数据

使用Apache Kudu客户端,对KafkaConnect Sink 进行扩展。 使用的Apache Kudu 的Java 客户端。突然有天发现作业无法提交,一直报错。 后来才发现这是Kudu自身的一种校验机制。为了忽略这种校验...

吐槽的达达仔
45分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部