【Spring】Spring自动装配深入浅出

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

set注入和构造注入有时在做配置时比较麻烦。所以框架为了提高开发效率,提供自动装配功能,简化配置。Spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性。自动装配属性有5个值可选,分别代表不同的含义。

1、byName

从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找<bean>标签的id属性值。如果有相同的,那么获取这个对象,实现关联。

整个Spring环境:表示所有的spring配置文件中查找,那么id不能有重复的。

2、byType

从Spring环境中获取目标对象时,目标对象中的属性会根据类型在整个spring环境中查找<bean>标签的class属性值。如果有相同的,那么获取这个对象,实现关联。

        缺点:如果存在多个相同类型的bean对象,会出错。

如果属性为单一类型的数据,那么查找到多个关联对象会发生错误。

如果属性为数组或集合(泛型)类型,那么查找到多个关联对象不会发生异常。

3、constructor(3.x以上已不能用)

使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。如果没找到则抛出异常

4、autodetect

自动选择:如果对象没有无参数的构造方法,那么自动选择constructor的自动装配方式进行构造注入。如果对象含有无参数的构造方法,那么自动选择byType的自动装配方式进行setter注入。

5、no

默认情况下,不自动装配,通过“ref”attribute手动设定。

<bean>标签的 autowire 属性,它负责自动装配<bean>标签定义 JavaBean 的属性。这样做可以省去很多配置 JavaBean 属性的标签代码,使代码整洁、美观。但是它也有负面影响,即使用自动装配之后,无法从配置文件中读懂 JavaBean 需要什么属性。自动装配存在很多不正确的装配问题,例如错误装载属性、“byType”属性和“constructor”属性对相同类型参数无法判断等。当然,将自动装配和手动装配混合使用也能解决此问题。下面通过一个实例来分析如何使用自动装配。

首先创建创建一个学生类 Student,定义学号、姓名、性别、年龄等属性,并添加对

应的 set()与 get()方法。程序代码如下。

package com.autobean;

public class Student {
	private String ID;
	private String name;
	private int age;
	private String sex;

	public String getID() {
		return ID;
	}

	public void setID(String iD) {
		ID = iD;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

}

同样创建一个教师类 Teacher,定义姓名、性别和年龄等属性,并添加对应的 set()与 get()方法。程序代码如下。

package com.autobean;

public class Teacher {
	private String name;
	private int age;
	private String sex;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

}

创建教学档案类 TeachFile,定义 Teacher 和 Student 两个属性,并添加 print()方法。用于输出教师与学生的信息。程序代码如下。

package com.autobean;

public class TeachFile {
	private Teacher teacher;
	private Student student;
	public TeachFile() {
	}
	public TeachFile(Teacher teacher, Student student) {
		this.teacher = teacher;
		this.student = student;
	}

	public Student getStudent() {
		return this.student;
	}

	public void setStudent(Student student1) {
		this.student = student1;
	}

	public Teacher getTeacher() {
		return teacher;
	}

	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}

	public void print() {
		System.out.println("------教师信息------");
		System.out.println("姓名:" + teacher.getName());
		System.out.println("年龄:" + teacher.getAge());
		System.out.println("性别:" + teacher.getSex());
		System.out.println();
		System.out.println("------学生信息------");
		System.out.println("学号:" + student.getID());
		System.out.println("姓名:" + student.getName());
		System.out.println("年龄:" + student.getAge());
		System.out.println("性别:" + student.getSex());
	}

}

在配置文件applicationContext.xml中定义刚刚创建的类,并为其赋值。其中 TeachFile 类采用了自动装配。程序代码如下。

<?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-3.2.xsd">

	<bean id="student" class="com.autobean.Student">
	    <property name="ID" value="80" />
	    <property name="name" value="阿王" />
	    <property name="age" value="23" />
	    <property name="sex" value="男" />
	</bean>
	<bean id="teacher" class="com.autobean.Teacher">
        <property name="name" value="何老师" />
        <property name="age" value="43" />
        <property name="sex" value="女" />
	</bean>
	<!-- 默认情况下,通过‘ref’来装配bean -->
	<bean id="teachFile1" class="com.autobean.TeachFile" >
	 <property name="teacher" ref="teacher" />
	 <property name="student" ref="student" />
	</bean>
    <!--根据byName自动装配bean -->
	<bean id="teachFile2" autowire="byName"  class="com.autobean.TeachFile" />
	  <!--根据byType自动装配bean -->
    <bean id="teachFile3" autowire="byType" class="com.autobean.TeachFile" />
	  <!--根据constructor自动装配bean -->
	<bean id="teachFile4" autowire="constructor" class="com.autobean.TeachFile"/>
</beans>

在这个配置文件中定义了 Student 类和 Teacher 类,并为姓名、年龄和性别属性赋值。在定义 TeachFile 类时,没有传递任何参数,而是采用了 autowire 属性自动配置 TeachFile类所需要的属性。下面编写一个主类 PrintInfo 类来输出档案信息。程序代码如下。

package com.autobean;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class PrintInfo {

	public static void main(String[] args) {
		Resource res = new ClassPathResource("applicationContext.xml");
		BeanFactory bf = new XmlBeanFactory(res);
		TeachFile tf1 = (TeachFile) bf.getBean("teachFile1");
		TeachFile tf2 = (TeachFile) bf.getBean("teachFile2");
		TeachFile tf3 = (TeachFile) bf.getBean("teachFile3");
		TeachFile tf4 = (TeachFile) bf.getBean("teachFile4");

		System.out.println("默认情况下,通过‘ref’来装配bean");
		tf1.print();
		System.out.println("根据byName自动装配bean");
		tf2.print();
		System.out.println("根据byType自动装配bean");
		tf3.print();
		System.out.println("根据constructor自动装配bean");
		tf4.print();

	}

}

输出结果:

四月 02, 2015 8:16:48 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
默认情况下,通过‘ref’来装配bean
------教师信息------
姓名:何老师
年龄:43
性别:女

------学生信息------
学号:80
姓名:阿王
年龄:23
性别:男
根据byName自动装配bean
------教师信息------
姓名:何老师
年龄:43
性别:女

------学生信息------
学号:80
姓名:阿王
年龄:23
性别:男
根据byType自动装配bean
------教师信息------
姓名:何老师
年龄:43
性别:女

------学生信息------
学号:80
姓名:阿王
年龄:23
性别:男
根据constructor自动装配bean
------教师信息------
姓名:何老师
年龄:43
性别:女

------学生信息------
学号:80
姓名:阿王
年龄:23
性别:男

在上面实例的配置文件 appContext.xml 中,TeachFile 类采用4种装配,将 Teacher
类和 Student 类注入到对应的属性中。语法格式如下。

<bean autowire="byName" id="teachFile" class="TeachFile" />

在 autowire 属性中指定类型为“byName”。autowire 属性共支持 5 种装配类型,下面
分别介绍每种装配类型的用法。
(1)no:autowire 采用的默认值,采用自动装配。必须使用 ref 直接引用其他 Bean,这样可以增加代码的可读性,并且不易出错。
(2)byName:以属性名区分自动装配。在容器中寻找与 JavaBean 的属性名相同的JavaBean,并将其自动装配到 JavaBean 中。如果用上面的实例来解释,TeachFile 类的实例对象 teachFile 包含的两个属性分别是 Teacher 类和 Student 类的实例对象,而配置文件中已经定义了这两个类的实例。在定义 teachFile 实例时指定了自动装配类型为“byName”,容器会自动寻找 teachFile 实例需要的属性(即 teacher 和 student 两个 JavaBean),并注入到 teachFile 实例中。此类自动装配类型存在错误装配 JavaBean 的可能,如果配置文件中定义了与需要自动装配的 JavaBean 属性相同而类型不同的 JavaBean,那么它会错误地注入不同类型的JavaBean。读者可以将上面实例中的配置文件修改一下,将 student 和 teacher 两个JavaBean 的类型保持不变,将名字调换一下,便会出现此问题。这时自动装配无法解决此问题,只能通过混合使用手动装配来指定装配哪个 JavaBean。
(3)byType:以属性类型区分自动装配。容器会自动寻找与 JavaBean 的属性类型相同的 JavaBean 的定义,并将其注入到需要自动装配的 JavaBean 中。如果将上面配置JavaBean 自动装配的类型修改为 byType,也可以实现相同的结果。这种自动装配类型也会出现无法自动装配的情况。例如在配置文件中再次添加一个Student 类或 Teacher 类的实现对象,byType 自动装配类型会因为无法自动识别装配哪一个 JavaBean 而抛出org.springframework.beans.factory.UnsatisfiedDependencyException 异常。要解决此
问题,只能通过混合使用手动装配来指定装配哪个 JavaBean。
(4)constructor:通过构造方法的参数类型自动装配。此类型会使容器自动寻找与JavaBean 的构造方法的参数类型相同的 Bean,并注入到需要自动装配的 JavaBean 中。它
与 byType 类型存在相同的无法识别自动装配的情况。
(5)autudetect:这是最后一个自动装配类型,它首先使用 constructor 方式自动装配,然后使用 byType 方式。当然它也存在与 byType 和 constructor 相同的异常情况。建
议在使用自动装配时,把容易出现问题的 JavaBean 使用手动装配注入依赖属性
         林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

时间: 2024-10-11 23:08:47

【Spring】Spring自动装配深入浅出的相关文章

Spring的自动装配在session监听器失效

先看代码 package com.oa.listener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.springframework.beans.factory.annotation.Autowired; import com.oa.service.Syste

Spring之自动装配bean

Spring之自动装配bean 最近学习Spring框架,参考资料是Spring IN ACTION----第一张内容飘过去~~ 从第二章的自动装配bean开始,不过学习Spring核心最重要的还是ioc的注入模式吧! 书上是这么说的----(概念问题,哈哈),首先普及几个概念 --------------------------------------------------------------------------------------------------------------

spring中自动装配bean

首先用@Component注解类: package soundsystem: import org.springframework.stereotype.Component; @Component public class TestBean{ …… } 开启组件扫描spring才能自动装配bean,创建一个@ComponentScan注解的类 package soundsystem: import org.springframework.context.annotation.componentS

spring的自动装配,骚话@Autowired的底层工作原理

前言 开心一刻 十年前,我:我交女票了,比我大两岁.妈:不行!赶紧分! 八年前,我:我交女票了,个比我小两岁,外地的.妈:你就不能让我省点心? 五年前,我:我交女票了,市长的女儿.妈:别人还能看上你?分了吧! 今年,我挺着大肚子踏进家门.妈:闺女啊,你终于开窍了 ! 前情回顾 Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现中讲到了spring对BeanPostProcessor的底层支持,并且知道了BeanPostProcessor的两个方法:postProce

Eureka 系列(03)Spring Cloud 自动装配原理

Eureka 系列(03)Spring Cloud 自动装配原理 [TOC] 本文主要是分析 Spring Cloud 是如何整合 Eureka 的,但不会具体分析 Eureka 的源码,之后的文章会对 Eureka 的源码做一个比较具体的分析. 1. Eureka Client 自动装配 org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.netflix.eureka.

spring boot 自动装配的实现原理和骚操作,不同版本实现细节调整,debug 到裂开......

开篇说明: 注解本身并没有什么实际的功能(非要说标记也是一个“实际”的功能的话,也可以算吧),隐藏在背后的注解处理器才是实现注解机制的核心.本篇将从这两个层面出发探索 spring boot 自动装配的秘密,并使用 spring boot 的自动装配机制来实现自动装配. 本次代码已经放到 github:https://github.com/christmad/code-share/tree/master/spring-boot-config-practice 代码中主要是做了 @Configur

Spring -- Bean自动装配&amp;Bean之间关系&amp;Bean的作用域

Bean的自动装配 Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 的 autowire 属性里指定自动装配的模式 有以下几种自动装配的类型: byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配. byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同. constructor(通过构造器自动装配):

Spring Autowire自动装配

在Spring中,支持 5 自动装配模式. no – 缺省情况下,自动配置是通过"ref"属性手动设定 byName – 根据属性名称自动装配.如果一个bean的名称和其他bean属性的名称是一样的,将会自装配它. byType – 按数据类型自动装配.如果一个bean的数据类型是用其它bean属性的数据类型,兼容并自动装配它. constructor – 在构造函数参数的byType方式. autodetect – 如果找到默认的构造函数,使用"自动装配用构造";

【Spring】—— 自动装配

一.Spring中装配bean的方式 1.在XML中显式配置 2.在Java中进行显式配置 3.隐士的bean发现机制和自动装配 二.自动装配示例 1.在需要装配到其他bean中的类中加入@Component注解 package study.spring.configure.auto; import org.springframework.stereotype.Component; /** * 第一步:将该类声明成一个组件类,括号内的参数为组件类的id自定义名称,也可以使用@Named. * s