系统学习Spring之Spring in action(五)
本文内容纲要:
- 每日一叨:- 文章导读:
- 1.通过XML实现Bean的自动装配
- 2.通过注解装配bean
- 知识点:
- 1.通过XML实现Bean的自动装配
- 2.通过注解装配bean
每日一叨:
原本想这个星期六和星期天把依赖注入和面向切面编程写完的,结果小姨来南京玩,写博客的计划泡汤了.只能拖到今天写了,一定要找时间弥补上....
文章导读:
1.通过XML实现Bean的自动装配
2.通过注解装配bean
知识点:
到现在为止,我们学习了如何用
注入的值也多,如果你还要用之前的方法配置会很繁琐。还好Spring提供了一种可以减少配置说是消除
1.通过XML实现Bean的自动装配
Spring提供了5种类型的自动装配.分别是byName,byType,constructor,autodetect,default
** **1)byName:匹配
若没有匹配的name或者id,则匹配失败
2)byType:匹配
若没有匹配的类型,则匹配失败.
3)constructor:匹配
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也可以用在构造方法上.
@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