欢迎关注公众号——小东方不败,每天更新技术文章
Bean的自动装配(自动注入)- autowire研究
准备这样的2个类:
package com.bones.bean;
/**
* @author : bones
* @version : 1.0
*/
public class Client {
private PhoneNumber phoneNumber;
public Client() {
}
public Client(PhoneNumber phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setPhoneNumber(PhoneNumber phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public String toString() {
return "Client{" +
"phoneNumber=" + phoneNumber +
'}';
}
}
package com.bones.bean;
/**
* @author : bones
* @version : 1.0
*/
public class PhoneNumber {
private Integer num;
public void setNum(Integer num) {
this.num = num;
}
}
Client类中组合了PhoneNumber类。
如果不应用autowire,需要这样赋值:
<bean id="client" class="com.bones.bean.Client">
<property name="phoneNumber">
<bean class="com.bones.bean.PhoneNumber"/>
</property>
</bean>
或者这样:
<bean id="phoneNumber" class="com.bones.bean.PhoneNumber"/>
<bean id="client" class="com.bones.bean.Client">
<property name="phoneNumber" ref="phoneNumber"/>
</bean>
如果自动装配,xml中的配置会变的简单:
<bean id="phoneNumber" class="com.bones.bean.PhoneNumber"/>
<bean id="client" class="com.bones.bean.Client" autowire="byName"/>
autowire="byName"
意思是,会自动装配属性名和id相同的bean。
举个例子:如果上面的phoneNumber
对象的id
变成phoneNumber1
,此时因为Client类的属性名phoneNumber
和id不匹配,就不会自动装配。(其实这个说法是错的,byName的自动装配跟set方法名和参数类型有关,跟属性名无关,后面有彩蛋)
autowire="byType"
根据类型去自动装配,此时不要求id值和属性名相同,但是一个容器中不建议有2个相同的对象,否则会引起歧义,编译就会有错:
这里补充:其实
byType
与set方法的参数类型有关。
彩蛋
至此貌似研究完了,但是后来发现一个问题:
很多人以为,byName的自动装配是跟类中的属性有关,其实不是,使用byName进行自动装配时,是利用Java的反射机制获取自动装配类中的set方法名,去掉set后将其首字母小写再到IOC容器中查找是否有对应的beanId,如果有则查看该bean的类型与set方法的参数类型是否匹配,匹配上了则调用set方法进行依赖注入。因此,byName的自动装配跟set方法名和参数类型有关,跟属性名无关。可以尝试将setNum中的N小写,如:setnum,其他不变,依然可以注入成功。也可以任意更改set方法名和beanId标识进行自动装配测试。
下面的测试就印证了上面的说法