系统学习Spring之Spring in action(五)

本文内容纲要:

- 每日一叨:

- 文章导读:

-     1.通过XML实现Bean的自动装配

-     2.通过注解装配bean

- 知识点:

-    1.通过XML实现Bean的自动装配

- 2.通过注解装配bean

每日一叨:

    原本想这个星期六和星期天把依赖注入和面向切面编程写完的,结果小姨来南京玩,写博客的计划泡汤了.只能拖到今天写了,一定要找时间弥补上....

文章导读:

    1.通过XML实现Bean的自动装配

    2.通过注解装配bean

知识点:

    到现在为止,我们学习了如何用向bean中注入值.在小一点的应用程序中,这种做法是个不错的选择.如果bean比较多,

注入的值也多,如果你还要用之前的方法配置会很繁琐。还好Spring提供了一种可以减少配置说是消除的技术.

   1.通过XML实现Bean的自动装配

  Spring提供了5种类型的自动装配.分别是byName,byType,constructor,autodetect,default

**  **1)byName:匹配标签中所有bean的name或者id与当前自动装配bean中properties名字相同的bean,并且自动注入到自动装配的bean中,

  若没有匹配的name或者id,则匹配失败

  2)byType:匹配标签中所有bean的类型与当前自动装配bean中properties中值的类型相同的bean,并且自动注入到自动装配的bean中,

  若没有匹配的类型,则匹配失败.

  3)constructor:匹配标签中所有bean的构造方法的参数类型与当前自动装配相匹配的bean,若没有匹配类型,则匹配失败.

  4)autodetect:autodetect的匹配策略是先通过constroctor进行匹配,若匹配失败,则进行byType匹配,若仍然没有匹配成功,则匹配失败.

  5)default:dafault是根据Spring configuration配置而来,可以是上面的任意一种. 

  byName事例:

public interface Game {

//获取游戏名称

public void getGameName();

}

public class War3 implements Game {

@Override

public void getGameName() {

// TODO Auto-generated method stub

System.out.println("大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.");

}

}

public class Dota implements Game {

//Dota游戏作者

private String author;

//Dota玩家同样会玩War3

private War3 war3;

public String getAuthor() {

return author;

}

public void setAuthor(String author) {

this.author = author;

}

public War3 getWar3() {

return war3;

}

public void setWar3(War3 war3) {

this.war3 = war3;

}

@Override

public void getGameName() {

// TODO Auto-generated method stub

System.out.println("大家好,我们名字叫Dota,来自 " + this.author + " 之手");

this.war3.getGameName();

}

}

  这是手动注入的配置:

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota">

<property name="author" value="冰蛙"></property>

<property name="war3" ref="war3"></property>

</bean>

  这是自动注入的配置:

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota" autowire="byName">

    <property name="author" value="冰蛙"></property>

</bean>

data实例中有一个com.ricky.zero.pojo.War3类型的属性,该属性的变量名为war3,所以bean被加载的时候会通过autowire的byName策略自动寻找

id或者name为war3的bean,完成自动注入.

事例测试:

ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");

Dota dota = (Dota)ctx.getBean("dota");

dota.getGameName();

测试结果:

大家好,我们名字叫Dota,来自 冰蛙 之手

大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.

不管有多少个properties通过ref属性去注入对象都不再去重新配置XML文件了,其优势不言而喻。

  byType事例:

只需要修改Spring配置文件即可.

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota" autowire="byType">

<property name="author" value="冰蛙"></property>

</bean>

data实例中有一个com.ricky.zero.pojo.War3类型的属性,所以bean被加载的时候会通过autowire的byType策略自动寻找类型为com.ricky.zero.pojo.War3

类型的bean,完成自动注入

直接运行测试并得到运行结果为:

大家好,我们名字叫Dota,来自 冰蛙 之手

大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.

byType有一个问题就是同一类型的bean不能同时出现.如下示例:

<bean id="war4" class="com.ricky.zero.pojo.War3"></bean>

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota" autowire="byType">

若都是同一个类型com.ricky.zero.pojo.War3,只是id不同,在autowire的byType策略下会抛异常,异常如下:

expected single matching bean but found 2: war4,war3

在autowire的byType策略下,出现两个相同类型Spring不会去猜你想要的是哪个,而是直接抛错,让你自己来解决,目前只能先确保一个类型在Spring context中

只有一个对应的bean.若同一类型必须要出现多个bean而且还要运用byType策略,Spring提供2种方法解决上述问题,一种是通过识别出重要的候选者,

另一种是消除byType搜索的候选者.

识别重要的候选者事例:

修改Spring configuration配置文件:

<bean id="war4" class="com.ricky.zero.pojo.War3"></bean>

<bean id="war3" class="com.ricky.zero.pojo.War3" primary="true"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota" autowire="byType">

<property name="author" value="冰蛙"></property>

</bean>

若在一个bean中加上parmary="true"属性,byType策略会首先注入当前bean.同类中,只能有一个primary="true"属性,否则也会抛异常.

还有一种方法是消除byType搜索的候选者:

<bean id="war4" class="com.ricky.zero.pojo.War3" ></bean>

<bean id="war3" class="com.ricky.zero.pojo.War3" autowire-candidate="false"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota" autowire="byType">

<property name="author" value="冰蛙"></property>

</bean>

若哪个bean后面有autowire-candidate="false"属性时,byType搜索的时候将会跳过有autowire-candidate="false"属性的bean.

两个事例的测试结果为:

大家好,我们名字叫Dota,来自 冰蛙 之手

大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.

constructor事例:

public class War3 implements Game {

@Override

public void getGameName() {

// TODO Auto-generated method stub

System.out.println("大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.");

}

}

public class DotaPlayer implements Player {

//已杀敌人总数

private int currentKill = 0;

private War3 war3;

//没有参数的构造方法 

public DotaPlayer(){}

//以基本类型为参数的构造方法

public DotaPlayer(int currentKill){

this.currentKill = currentKill;

};

//以对象类型为参数的构造方法

public DotaPlayer(War3 war3){

this.war3 = war3;

};

//重写Player类中的play()方法

@Override

public void play() {

// TODO Auto-generated method stub

System.out.println("DOTA玩家已经杀了"+ this.currentKill +"个敌人.");

war3.getGameName();

}

}

Spring Configuration配置文件如下:

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dotaPlayer" class="com.ricky.zero.pojo.DotaPlayer" autowire="constructor">

</bean>

autowire="constructor"作用是搜寻与构造方法参数列表中参数变量的名称与bean的name相同的bean,然后注入构造方法中.

运行测试

ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");

DotaPlayer dotaPlayer = (DotaPlayer)ctx.getBean("dotaPlayer");

dotaPlayer.play();

测试结果:

DOTA玩家已经杀了0个敌人.

大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.

default:默认的自动装配策略是空,可以自定义默认的策略.

在你使用自动装配策略的时候,仍然可以使用手动指定装配.手动指定装配将会overriding自动装配,这样的混合装配在constructor-autowiring中是不允许的.

Spring必须装配所有的arguments.

2.通过注解装配bean

  从Spring的2.5版本,Spring就支持用注解的方式去自动装载bean的properties.用注解的方式和用XML配置文件的方式大同小异.但是用注解可以更细粒度的

装配bean.注解在Spring configuration中默认是关闭的,如果要想使用注解,首先要打开注解.最简单的方法是在标签下添加如下语句.

<context:annotation-config/>

这个标签告诉Spring你打算使用注解去装配bean,当你使用注解的时候,注解可以装配值到properties,method,constructors中.

Spring支持3种自动装配注解:@Autowired,@Inject,@Resource.

@Autowired事例:

当你想用@Autowired去装配bean的id为dota的properties为wa3的bean的时候.(感觉不好理解就看下面的例子,一看就懂了,可能我的表达能力不有,慢慢提高哈.)

@Autowire注解自动装配的策略是byType

可以在properties的setter方法上加这个注解:

@Autowired

public void setWar3(War3 war3) {

this.war3 = war3;

}

Spring configuration配置文件:

//用于打开Spring注解

<context:annotation-config />

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota">

<property name="author" value="冰蛙"></property>

</bean>

在setter方法上加@Autowired相当于 这个标签的功能.@Autowired比XML配置

要简单,精巧,

@Autowired也可以用在构造方法上.

@Autowired

public Dota(War3 war3) {

this.war3 = war3;

}

运行两次使用@Autowired的测试,并得到结果如下:

大家好,我们名字叫Dota,来自 冰蛙 之手

大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.

@Autowired也可以直接在properties上使用,而不用在setter方法上就可以完成注入.用注解以后就废除setter方法,直接在属性上注解.

例:

@Autowired

private War3 war3;

运行测试结果如上.

当@Autowired没有搜索到匹配的bean,或者多个bean同时被注入的时候,Spring将会抛异常.

当没有搜索到匹配的bean的时候会抛异常:

expected at least 1 bean which qualifies as autowire candidate for this dependency

因为@Autowired有一个缺省值@Autowired(required=true),当required为true的时候,若没有匹配到bean则会抛异常.若把required设置成false,

则不会抛出上述异常,但是当你用到该属性的时候,会抛NullPointerException异常,因为你注入失败,属性值为null.

当有多个bean同时匹配时,将会抛出异常如下:

<bean id="war3" class="com.ricky.zero.pojo.War3"></bean>

<bean id="war4" class="com.ricky.zero.pojo.War3"></bean>

<bean id="dota" class="com.ricky.zero.pojo.Dota">

<property name="author" value="冰蛙"></property>

</bean>

expected single matching bean but found 2: war3,war4

为了找这个异常的时候,发现一个有趣的事情,本来书上写@Autowired是按byType策略去注入的.当我在

//Dota玩家同样会玩War3

@Autowired

private War3 war3;

当我的就是名为war3 ,与Spring configuration中的一个bean的id名称相同时,运行测试不会抛异常.若把变量名改成与两个bean不一样,则会抛上述异常.

该问题大家也考虑下,现在没有时间研究,有时间来探究下.

这种异常可以通过Spring的又一个注解来解决@Qualifier.

@Qualifier是用于通过ID来选择你想要的bean.简单来说就是@Autowired搜索出所有相同类型的候选bean,@Qualifier(value="要选择bean的id")

在这些候选bean中选择id与@Qualifier的value相同的bean.

//Dota玩家同样会玩War3

@Autowired

@Qualifier(value="war3")

private War3 war3;

这样就解决上述的异常问题了.

--------------------------------申明----------------------------       

                  本文可以免费阅读以及转载,转载时请注明出处.      

                  本人邮箱:Ricky_LS@163.com

                  Thank you for your corporation.

本文内容总结:每日一叨:,文章导读:,    1.通过XML实现Bean的自动装配,    2.通过注解装配bean,知识点:,   1.通过XML实现Bean的自动装配,2.通过注解装配bean,

原文链接:https://www.cnblogs.com/yjhk/archive/2013/03/26/2981767.html

以上是 系统学习Spring之Spring in action(五) 的全部内容, 来源链接: utcz.com/z/296114.html

回到顶部