一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配带来的好处比起来,明确清晰的配置文档更加有说服力一些。
一、自动装配bean
spring ioc容器可以自动装配bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式。
有以下三种方法:
- byType
- byName
- constructor
简单解释:
(1)byType
根据类型自动装配,如果ioc容器里有多个和目标bean类型一致的bean,在这种情况下,spring将无法判定那个bean最适合该属性,所以无法进行自动装配。
(2)byName
根据名称自动装配,必须将目标bean的名称和属性名设置的完全相同。
(3)constructor
通过构造器自动装配,当bean中存在多个构造器的时候,这种自动装配方式将会非常复杂,不推荐使用。
二、手动装配
1 2 3 |
<bean id="kami" class="autowire.kami" p:alive="alive666" p:dead="dead233"></bean> <bean id="god" class="autowire.god" p:save="save233" p:kill="save456"></bean> <bean id="xie" class="autowire.xie" p:name="xie" p:god-ref="god" p:kami-ref="kami"></bean> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package autowire; public class xie { private String name; private god god; private kami kami; public String getName() { return name; } public void setName(String name) { this.name = name; } public god getGod() { return god; } public void setGod(god god) { this.god = god; } public kami getKami() { return kami; } public void setKami(kami kami) { this.kami = kami; } @Override public String toString() { return "xie [name=" + name + ", god=" + god + ", kami=" + kami + "]"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package autowire; public class god { private String save; private String kill; public String getSave() { return save; } public void setSave(String save) { this.save = save; } public String getKill() { return kill; } public void setKill(String kill) { this.kill = kill; } @Override public String toString() { return "god [save=" + save + ", kill=" + kill + "]"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package autowire; public class kami { private String alive; private String dead; public String getAlive() { return alive; } public void setAlive(String alive) { this.alive = alive; } public String getDead() { return dead; } public void setDead(String dead) { this.dead = dead; } @Override public String toString() { return "kami [alive=" + alive + ", dead=" + dead + "]"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package autowire; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class main { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); xie xie = (autowire.xie) applicationContext.getBean("xie"); System.out.println(xie.toString()); } } |
运行结果:
1 |
xie [name=xie, god=god [save=save233, kill=save456], kami=kami [alive=alive666, dead=dead233]] |
这是典型的手动装配。
三、自动装配
(1)byName
只需要改动一行:
1 |
<bean id="xie" class="autowire.xie" p:name="xie" autowire="byName"></bean> |
把之前设置bean映射变成autowire=”byName”,就可以按名字自动填充了
注意:bean的id为god、kami,和我的具体类名是相对应的。这样spring就可以自动映射。
运行结果:
1 |
xie [name=xie, god=god [save=save233, kill=save456], kami=kami [alive=alive666, dead=dead233]] |
成功输出,自动装配成功。
我们改动一下试试?
1 |
<bean id="kami2" class="autowire.kami" p:alive="alive666" p:dead="dead233"></bean> |
运行结果:
1 |
xie [name=xie, god=god [save=save233, kill=save456], kami=null] |
当时就无法装配了。
所以byName的方式一定要把bean的id和class名称对应才能自动装配。
(2)byType
1 2 3 |
<bean id="kami" class="autowire.kami" p:alive="alive666" p:dead="dead233"></bean> <bean id="god" class="autowire.god" p:save="save233" p:kill="save456"></bean> <bean id="xie" class="autowire.xie" p:name="xie" autowire="byType"></bean> |
运行结果:
1 |
xie [name=xie, god=god [save=save233, kill=save456], kami=kami [alive=alive666, dead=dead233]] |
正常输出。
但是byType有个大问题,这样配置的情况下:我们配置了god1,god2:
1 2 3 4 |
<bean id="kami" class="autowire.kami" p:alive="alive666" p:dead="dead233"></bean> <bean id="god1" class="autowire.god" p:save="save233" p:kill="save456"></bean> <bean id="god2" class="autowire.god" p:save="save456" p:kill="save789"></bean> <bean id="xie" class="autowire.xie" p:name="xie" autowire="byType"></bean> |
运行报错:
1 2 |
No qualifying bean of type [autowire.god] is defined: expected single matching bean but found 2: god1,god2 Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'xie' defined in class path resource [beans.xml]: Unsatisfied dependency expressed through bean property 'god': No qualifying bean of type [autowire.god] is defined: expected single matching bean but found 2: god1,god2; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [autowire.god] is defined: expected single matching bean but found 2: god1,god2 |
因为两个类型的构造是相似的,spring不知道自动装配哪一个了,所以报错。
如果ioc容器中有一个以上的类型匹配的bean,则报异常。
(3)constructor
不建议使用,不方便,不演示。
四、自动装配的缺点
在bean配置文件里设置autowire属性进行自动装配将会装配bean的所有属性,然而,若只希望装配个别属性时,autowire就不够灵活了。
autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之。
五、总结
一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配带来的好处比起来,明确清晰的配置文档更加有说服力一些。