# 装配Spring Bean

装配Spring Bean

目标:

  1. 掌握3种依赖注入的方式

  2. 掌握如何使用XML装配Bean

  3. 掌握如何使用注解方式装配Bean及消除歧义

  4. 掌握如何使用profile 和条件装配Bean

  5. 掌握Bean 的作用域

  6. 了解Spring EL的简易使用

依赖注入的3种方式:

  • 构造器注入

  • setter注入

  • 接口注入

构造器注入:

构造器注入依赖于构造方法实现,而构造方法可以是有参数或是无参数的,在大部分的情况下,我们都是通过类的构造器方法来创建类的对象,Spring也可以采用反射的方式,通过构造方法来完成注入,这就是构造器注入的原理。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n26" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter9.pojo;

public class Role {
private Long id;
private String roleName;
private String note;

public Role(String roleName, String note) {
this.roleName = roleName;
this.note = note;
}

public Long getId() {
return id;
}

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

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

}
</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n27" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="role_1" class="com.ssm.chapter9.pojo.Role">
<constructor-arg index="0" value="高级工程师" />
<constructor-arg index="1" value="重要人员" />
</bean></pre>

constructor-arg元素用于定义类构造方法的参数,其中index用于定义参数的位置,而value则是设置值。

这个注入比较简单,但无法应用大量参数的程式

使用setter注入:

setter注入是Spring中最主流注入方式,它利用Java Bean规范所定义的setter方法来完成注入,灵活且可读性高。

首先把构造方法声明为无参数的,然后使用setter注入为其设置对应的值,其实是通过Java反射技术得以实现。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n33" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter9.pojo;

public class Role {
private Long id;
private String roleName;
private String note;

public Role() {

}
public Role(String roleName, String note) {
this.roleName = roleName;
this.note = note;
}

public Long getId() {
return id;
}

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

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

}</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n34" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="role2" class="com.ssm.chapter9.pojo.Role">
<property name="roleName" value="高级工程师" />
<property name="note" value="重要人员" />
</bean></pre>

这样Spring就会通过反射调用没有参数的构造方法生成对象,同时通过反射对应的setter注入配置的值了,这种方式是Spring最主要的方式。

接口注入:

接口注入主要来自外界

装配Bean概述

Spring 中提供3中方法进行配置:

  • 在xml中显示配置。

  • 在Java的接口和类中实现配置。

  • 隐式配置的接口发现机制和自动装配原则

3种方式优先级:

  1. 基于约定优于配置的原则,最优先的应该是通过隐式Bean的发现机制和自动装配的原则.这样的好处是减少程序开发者的决定权,简单又不失灵活。

  2. 在没有办法使用自动装配原则的情况下应该优先考虑Java接口和类中实现配置,这样的好处是避免xml配置的泛滥,也更为容易。这种场景典型的例子是一个父类有多个子类,比如学生类有两个子类:男生类和女生类,通过IoC容器初始化一个学生类,容器将无法知道使用哪个子类去初始化,这个时候可以使用Java的注解配置去指定。

  3. 在上述方法无法使用的情况下,那么只能选择xml去配置Spring IoC容器。由于现实工作中常常用到第三方的类库,有些类 并不是我们开发的,我们无法修改里面的代码,这个时候就通过xml的方式配置使用了。

通过XML配置配置装配Bean

xml对于刚接触Spring IoC容器的人来说更为清晰明了,使用xml装配Bean需要定义对应的Spring Bean的元素。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n57" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><?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-4.0.xsd">

</beans></pre>

装配简易值

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n59" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="role2" class="com.ssm.chapter9.pojo.Role">
<property name="id" value="1" />
<property name="roleName" value="高级工程师" />
<property name="note" value="重要人员" />
</bean></pre>

  • id="role2" id属性是spring找到的一个Bean的编号,不过id不是一个必须的属性,如果没有声明它,那么Spring将会采用“全限定名#{number}”的格式编号。com.ssm.chapter9.pojo.Role#0==bean id="role2" class="com.ssm.chapter9.pojo.Role"

  • class显然是一个类的全限定名

  • property元素是定义类的属性,其中name属性定义的是属性的名称,而value是其值。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n67" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <bean id="source" class="com.ssm.chapter9.pojo.Source">
<property name="fruit" value="橙汁" />
<property name="sugar" value="少糖" />
<property name="size" value="大杯" />
</bean>

<bean id="juiceMaker2" class="com.ssm.chapter9.pojo.JuiceMaker2">
<property name="beverageShop" value="贡茶" />
<property name="source" ref="source" />
</bean></pre>

装配集合:

有些时候要一些复杂的装配工作,比如Set,Map,List,Array,Properties等。先定义Bean

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n71" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter10.pojo;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class ComplexAssembly {

private Long id;
private List<String> list;
private Map<String, String> map;
private Properties props;
private Set<String> set;
private String[] array;

public Long getId() {
return id;
}

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

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 Properties getProps() {
return props;
}

public void setProps(Properties props) {
this.props = props;
}

public Set<String> getSet() {
return set;
}

public void setSet(Set<String> set) {
this.set = set;
}

public String[] getArray() {
return array;
}

public void setArray(String[] array) {
this.array = array;
}

}</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n72" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="complexAssembly" class="com.ssm.chapter10.pojo.ComplexAssembly">
<property name="id" value="1" />
<property name="list">
<list>
<value>value-list-1</value>
<value>value-list-2</value>
<value>value-list-3</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value-key-1" />
<entry key="key2" value="value-key-2" />
<entry key="key3" value="value-key-3" />
</map>
</property>
<property name="props">
<props>
<prop key="prop1">value-prop-1</prop>
<prop key="prop2">value-prop-2</prop>
<prop key="prop3">value-prop-3</prop>
</props>
</property>
<property name="set">
<set>
<value>value-set-1</value>
<value>value-set-2</value>
<value>value-set-3</value>
</set>
</property>
<property name="array">
<array>
<value>value-array-1</value>
<value>value-array-2</value>
<value>value-array-3</value>
</array>
</property>
</bean></pre>

  • List属性为对应的<list>元素进行装配,然后通过多个<value>元素设值。

  • Map属性为对应的<map>元素进行装配,然后通过多个<entry>元素设值,只是entry包含一个键(key)和一个值(value)的设值。

  • Properties属性,为对应的<Properties>元素进行装配,然后通过多个<Property>元素设值,只是property元素有一个必填属性key,然后可以设值。

  • Set属性为对应的<set>元素进行装配,然后通过多个<value>元素设值.

  • 对于数组而言,<array>元素进行装配,然后通过多个<value>元素设值.

从上面看到对字符串的各个集合加载,但是有些时候可能需要更为复杂的装载,比如一个List可以是一个系列类的对象,又如一个Map集合类,键可以是一个类的对象,而值也要是一个类的对象。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n85" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter10.pojo;

public class Role {
private Long id;
private String roleName;
private String note;

public Role() {
}

public Role(Long id, String roleName, String note) {
this.id = id;
this.roleName = roleName;
this.note = note;
}

public Long getId() {
return id;
}

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

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

}
</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n86" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter10.pojo;

public class User {
private Long id;
private String userName;
private String note;

public Long getId() {
return id;
}

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

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

}
</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n87" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.ssm.chapter10.pojo;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class UserRoleAssembly {

private Long id;
private List<Role> list;
private Map<Role, User> map;
private Set<Role> set;

public Long getId() {
return id;
}

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

public List<Role> getList() {
return list;
}

public void setList(List<Role> list) {
this.list = list;
}

public Map<Role, User> getMap() {
return map;
}

public void setMap(Map<Role, User> map) {
this.map = map;
}

public Set<Role> getSet() {
return set;
}

public void setSet(Set<Role> set) {
this.set = set;
}

}
</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n88" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="role1" class="com.ssm.chapter10.pojo.Role">
<property name="id" value="1" />
<property name="roleName" value="role_name_1" />
<property name="note" value="role_note_1" />
</bean>

<bean id="role2" class="com.ssm.chapter10.pojo.Role">
<property name="id" value="2" />
<property name="roleName" value="role_name_2" />
<property name="note" value="role_note_2" />
</bean>

<bean id="user1" class="com.ssm.chapter10.pojo.User">
<property name="id" value="1" />
<property name="userName" value="user_name_1" />
<property name="note" value="role_note_1" />
</bean>

<bean id="user2" class="com.ssm.chapter10.pojo.User">
<property name="id" value="2" />
<property name="userName" value="user_name_2" />
<property name="note" value="role_note_1" />
</bean>

<bean id="userRoleAssembly" class="com.ssm.chapter10.pojo.UserRoleAssembly">
<property name="id" value="1" />
<property name="list">
<list>
<ref bean="role1" />
<ref bean="role2" />
</list>
</property>
<property name="map">
<map>
<entry key-ref="role1" value-ref="user1" />
<entry key-ref="role2" value-ref="user2" />
</map>
</property>
<property name="set">
<set>
<ref bean="role1" />
<ref bean="role2" />
</set>
</property>
</bean></pre>

这里定义了两个角色Bean(role1和role2)和两个用户Bean(user1和user2),他们和之前定义没有什么不同,只是后面的定义略微不同而已。

  • List属性为对应的<list>元素定义注入,然后使用多个<ref>元素的Bean属性去引用之前定义好的Bean。

  • Map属性使用<map>元素定义注入,然后使用多个<entry>元素的key-ref属性去引用之前定义好的Bean作为键,而用value-ref属性去引用之前定义好的Bean作为值。

  • Set属性使用<set>元素定义注入,然后使用多个<ref>元素的Bean属性去引用之前定义好的Bean

命名空间装配

Spring还提供对应的命名空间的定义,只是在使用命名空间的时候要先引入对应的命名空间和xml模式。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="xml" cid="n100" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" 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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="role1" class="com.ssm.chapter10.pojo.Role"
c:_0="1" c:_1="role_name_1" c:_2="role_note_1" />
<bean id="role2" class="com.ssm.chapter10.pojo.Role"
p:id="2" p:roleName="role_name_2" p:note="role_note_2" />
<bean id="user1" class="com.ssm.chapter10.pojo.User"
p:id="1" p:userName="role_name_1" p:note="user_note_1" />
<bean id="user2" class="com.ssm.chapter10.pojo.User"
p:id="2" p:userName="role_name_2" p:note="user_note_2" />

<util:list id="list">
<ref bean="role1" />
<ref bean="role2" />
</util:list>

<util:map id="map">
<entry key-ref="role1" value-ref="user1" />
<entry key-ref="role2" value-ref="user2" />
</util:map>

<util:set id="set">
<ref bean="role1" />
<ref bean="role2" />
</util:set>

<bean id="userRoleAssembly" class="com.ssm.chapter10.pojo. UserRoleAssembly"
p:id="1" p:list-ref="list" p:map-ref="map" p:set-ref="set" />
</beans></pre>

xmlns:c="http://www.springframework.org/schema/c"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:util="http://www.springframework.org/schema/util"

  • 注意加粗的代码,它们定义了XML的命名空间,这样才能在内容里面使用p和c这样的前缀定义

  • id为role1的角色定义,c:0代表构造方法的第一个参数,c:1代表的是第2个,c:_2代表的是第3个,以此类推。

  • id为role2的角色定义,p代表引用属性,其中p:id=“2”以2为值,使用setId方法设置,roleName,note属性也是一样的道理

通过注解装配Bean

从上面的例子已知如何使用XML的方式去装配Bean,但更多的时候已经不推荐使用XMl的方式去装配Bean,更多时候回考虑使用注解(annotation)的方式去装配Bean,使用注解方式可以减少xml的配置,注解功能更为强大,它既能实现XML的功能,也提供了自动装配的功能,采用了自动装配后,程序员所需要做的决断就少了,更有利对程序的开发,这就是“约定优于配置”的开发原则。

在Spring中,它提供了两种方式来让Spring IoC容器发现Bean。

  • 组件扫描:通过定义资源的方式,让Spring IoC容器扫描对应的包,从而把Bean装配进来。

  • 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。

通过扫描和自动装配,大部分的工程都可以用Java配置完成,而不是xml,可以有效减少配置和引入大量xml。

如果系统存在多个公共的配置文件(多个properties和xml文件)或第三方资源,使用xml配置会更加明确。

以注解为主,以xml配置为辅。

使用@Component裝配Bean

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n123" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "role")
public class Role {
@Value("1")
private Long id;
@Value("role_name_1")
private String roleName;
@Value("role_note_1")
private String note;

public Long getId() {
return id;
}

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

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

}
</pre>

注意註解@Component(value = "role"),@Value("1")

  • 註解@Component代表Spring IoC会把这个类扫描生成Bean实例,而其中的value属性代表在Spring中的id,这就相当于XML方式定义的Bean的id,(<bean id="role_1"class="com.ssm.chapter9.pojo.Role">也可以简写成@Component("role"),甚至直接写成@Componen,对于不写的,Spring IoC容器就默认类名,但是以首字母小写的形式作为id,为其生成对象,配置到容器中。

  • 注解@Value代表的是值得注入,这里只是简单注入一些值,其中id是一个long型,注入的时候Spring会为其转换类型。

Spring IoC扫描类

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n131" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.pojo;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class PojoConfig {

}
</pre>

注意:package com.zw.pojo; @ComponentScan

  • 包名和代码清单需要一致(package com.zw.pojo;)

  • @ComponentScan代表进行扫描,默认是扫描当前包的路径,POJO的包名和它保持一致才能扫描,否则没有的。

测试:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n139" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.zw.pojo.PojoConfig;
import com.zw.pojo.Role;

public class Demo1Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role=context.getBean(Role.class);
System.out.println(role.getId());
}

}
</pre>

此处有两个明显的弊端:

  1. 对于@ComponentScan注解,它只扫描所在包的Java类,但是更多的时候真正需要的是可以扫描所指定的类

  2. 上面只是注入了一些简单的值,而没有注入对象,同样在现实的开发可以注入对象是十分重要的

@ComponentScan有两个配置项:

  1. basePackages:base Packages Package+s Package表示包,s表示多个包。

  2. basePackageClasses:base Package Classes Class+es Class表示类,es表示多个类。

验证@ComponentScan的两个配置项,首先定义一个接口RoleService

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n153" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.service;

import com.zw.pojo.Role;

public interface RoleService {
public void printRoleInfo(Role role);

}
</pre>

使用接口编写一些操作类是Spring所推荐的,它可以将定义和实现分离,这样就更为灵活。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n155" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.service.impl;

import org.springframework.stereotype.Component;

import com.sun.org.apache.xerces.internal.impl.dv.dtd.IDDatatypeValidator;
import com.zw.pojo.Role;
import com.zw.service.RoleService;
@Component
public class RoleServiceImpl implements RoleService {

@Override
public void printRoleInfo(Role role) {
// TODO Auto-generated method stub
System.out.println("id="+role.getId());
System.out.println("roleName="+role.getRoleName());
System.out.println("note="+role.getNote());
}

}
</pre>

这里的@ComponentScan表明它是一个Spring所需要的Bean。而且也实现了对应的RoleService接口所定义的printRoleInfo方法,

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n158" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.config;

import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;

import org.springframework.context.annotation.ComponentScan;

import com.zw.pojo.Role;
import com.zw.service.impl.RoleServiceImpl;

@ComponentScan(basePackageClasses= {Role.class,RoleServiceImpl.class})//重构项目使用它,便于报错读取
//@ComponentScan(basePackages= {"com.zw.pojo.Role","com.zw.service"}) //项目优先使用它,可读性比较好

public class ApplicationConfig {

}
</pre>

注意:

  • 这是对扫描包的定义,可以采用任意一个@ComponentScan去定义,也可以取消代码中的注释。

  • 如果采用多个@ComponentScan去定义对应的包,但是每定义一个@ComponentScan,Spring就会产生一个新的对象,也就是所配置的Bean将会生成多个实例,这往往不是我们所需要的。

  • 对于已定义的basePackagesbasePackageClasses@ComponentScan,Spring会进行专门的区分,也就是说在同一个@ComponentScan中即使重复定义相同的包或者存在其子包的定义,也不会造成因一个Bean的多次扫描,而导致一次配置生成多个对象。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n167" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.zw.config.ApplicationConfig;
import com.zw.pojo.PojoConfig;
import com.zw.pojo.Role;
import com.zw.service.RoleService;
import com.zw.service.impl.RoleServiceImpl;

public class Demo1Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
test2();
}

private static void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role=context.getBean(Role.class);
System.out.println(role.getId());
}
private static void test2() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Role role=context.getBean(Role.class);
RoleService roleService=context.getBean(RoleService.class);
roleService.printRoleInfo(role);
context.close();

}

}
</pre>

自动装配--@Autowired:

前面提到两个问题之一就是没有注入对象,关于这个问题,在注解中略微有点复杂。大部分的情况下建议使用自动装配,因为可以减少配置的复杂度。前面的Spring学习,Spring是先完成Bean的定义和生成,然后寻找需要注入的资源。

<pre mdtype="fences" cid="n170" lang="java" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.service;

public interface RoleService2 {
public void printRoleInfo();

}
</pre>

Spring 推荐的接口方式,这个更灵活。因为将定义和实现分离了。

<pre mdtype="fences" cid="n174" lang="java" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zw.pojo.Role;
import com.zw.service.RoleService2;
@Component("RoleService2")

public class RoleServiceImpl2 implements RoleService2 {
@Autowired
private Role role=null;

public Role getRole() {
return role;
}

public void setRole(Role role) {
this.role = role;
}

@Override
public void printRoleInfo() {
// TODO Auto-generated method stub
System.out.println("id="+role.getId());
System.out.println("roleName="+role.getRoleName());
System.out.println("note="+role.getNote());
}

}
</pre>

@Autowired

private Role role=null;

@Autowired注解,表示在Spring IoC定位所有的Bean后,这个字段需要按类型注入,这样IoC容器就会寻找资源,然后将其注入。

<pre mdtype="fences" cid="n176" lang="java" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.zw.config.ApplicationConfig;
import com.zw.pojo.PojoConfig;
import com.zw.pojo.Role;
import com.zw.service.RoleService;
import com.zw.service.RoleService2;
import com.zw.service.impl.RoleServiceImpl;

public class Demo1Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
test3();
}

private static void test1() {
ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role=context.getBean(Role.class);
System.out.println(role.getId());
}
private static void test2() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Role role=context.getBean(Role.class);
RoleService roleService=context.getBean(RoleService.class);
roleService.printRoleInfo(role);
context.close();

}

private static void test3() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleService2 roleService = context.getBean(RoleService2.class);
roleService.printRoleInfo();
context.close();

}

}
</pre>

自动装配的歧视性(@Primary和@Qualifier):

@Autowired在一个接口有多个实现类的时候无法使用

<pre mdtype="fences" cid="n194" lang="java" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.service.impl;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import com.zw.pojo.Role;
import com.zw.service.RoleService;
@Component("roleService3")
//@Primary //测试@Primary 一个接口存在多个实现类 区分优先处理
public class RoleServiceImpl3 implements RoleService{

@Override
public void printRoleInfo(Role role) {
// TODO Auto-generated method stub
System.out.println("id ="+role.getId());
System.out.println(",roleName ="+role.getRoleName());
System.out.println("roleService3note ="+role.getNote());
}

}
</pre>

在新建一个RoleController类,它有个字段RoleService类型。

<pre mdtype="fences" cid="n201" lang="java" class="md-fences md-end-block ty-contain-cm modeLoaded md-focus" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.zw.controlller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zw.pojo.Role;
import com.zw.service.RoleService;
@Component
//Controlller 控制器
public class RoleControlller {
@Autowired
private RoleService roleService=null;
public void printRole(Role role) {
roleService.printRoleInfo(role);

}

}
</pre>

这里的字段 RoleService是一个RoleService接口类型。RoleService有两个实现类。分别是RoleServiceImpl和RoleServiceImpl3,这个时候Spring IoC容器就会犯糊涂,无法判断把那个对象注入进来,于是就会抛出异常。这样@Autowired就失败了。

//@Primary //测试@Primary 一个接口存在多个实现类 区分优先处理

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容