spring的注入方式分为两种:设值注入和构造注入,不管是哪种方式都是为了注入依赖对象的。
设值注入方式比较常用。所谓的设值注入是指通过类中的setxxx方法来注入,这种方式简单直观。
<bean class="cn.itouchtv.Person" id="person" >
<property name="age" value="10"></property>
<property name="name" value="cjh"></property>
<property name="address" ref="address"></property>
</bean>
<bean class="cn.itouchtv.Address" id="address">
<property name="province" value="广东"></property>
<property name="city" value="广州" > </property>
</bean>
这里的注入方式都是通过property这个标签来注入,name代表相关的类的属性名称,value代表这个值。当需要引用IOC中的某个bean的时候使用ref来引用,对应的值用IOC中bean的id来表示,比如这里用到ref="address",那么就是说引用IOC中的address这个id对应的bean。
这中注入的方式都是主动的,还可以通过自动的方式注入。使用bean中的autowire属性:
<bean class="cn.itouchtv.Person" id="person" autowire="byType">
<property name="age" value="10"></property>
<property name="name" value="cjh"></property>
</bean>
<bean class="cn.itouchtv.Address" id="address">
<property name="province" value="广东"></property>
<property name="city" value="广州" > </property>
这里通过类型自动注入,这里要注意的是当同个类型的bean有两个时,会报错。还可以
autowire="byName",通过类的属性的名字和IOC容器中的bean的id来匹配。
构造器注入:这个方式有时候会显得很难阅读,代码臃肿。当有多个构造器的时候,
<bean class="cn.itouchtv.Person" id="person1" autowire="byName">
<constructor-arg value="cjh"></constructor-arg>
<constructor-arg value="23"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>
构造器注入用到<constructor-arg>这个标签,其实也有value和ref这些属性用于复制和引用IOC容器中的bean。构造器的注入配置中还可以通过:bean标签的index属性来指明注入的属性的顺序。其实上述的的顺序没写,默认就是0 1 2
<bean class="cn.itouchtv.Person" id="person1" autowire="byName">
<constructor-arg value="cjh" index="0"></constructor-arg>
<constructor-arg ref="address" index="2"></constructor-arg>
<constructor-arg value="23" index="1"></constructor-arg>
</bean>
但是如果是有两个三个参数的构造器的话,那么这个构造器必须是有不同类型的参数,或者是参数类型的顺序不同,不然会报错。也就是说,不可以有按顺序类型相同,个数相同的的构造器。
那么这个index就可以制定是使用哪个构造器了。假设出现赋值都满足的构造器就出现歧义 。
package cn.itouchtv;
public class Person {
private String name;
private int age;
private Address address;
private long weight;
public Person() {
}
public Person(String name, long weight, Address address) {
this.name = name;
this.address = address;
this.weight = weight;
}
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long getWeight() {
return weight;
}
public void setWeight(long weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
", weight=" + weight +
'}';
}
}
很明显,上述的构造器赋值两个都是可以的。
<bean class="cn.itouchtv.Person" id="person1" autowire="byName">
<constructor-arg value="cjh" ></constructor-arg>
<constructor-arg value="23"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>
<bean class="cn.itouchtv.Person" id="person2" autowire="byName">
<constructor-arg value="cjh" ></constructor-arg>
<constructor-arg value="56"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>
结果:
person1: Person{name='cjh', age=23, address=Address{province='广东', city='广州'}, weight=0}
person2: Person{name='cjh', age=56, address=Address{province='广东', city='广州'}, weight=0}
那么这两个都会赋值给同一个bean,我这里是都给age了。此时为了防止出现歧义,可以制定参数的类型。
加上type="long",那么对应的就会赋值给weight了。
<bean class="cn.itouchtv.Person" id="person1" autowire="byName">
<constructor-arg value="cjh" ></constructor-arg>
<constructor-arg value="23"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>
<bean class="cn.itouchtv.Person" id="person2" autowire="byName">
<constructor-arg value="cjh" ></constructor-arg>
<constructor-arg value="56" type="long"></constructor-arg>
<constructor-arg ref="address"></constructor-arg>
</bean>
结果:person1: Person{name='cjh', age=10, address=Address{province='广东', city='广州'}, weight=0}
person2: Person{name='cjh', age=0, address=Address{province='广东', city='广州'}, weight=56}
建议:这个是网上看到的建议》建议采用设值注入为主,构造注为辅的策略,对于依赖关系不变的,使用构造注入,其他使用设值注入,比如datasource的注入,建议使用构造注入。
这里而外插入xml配置的继承。这个跟java的继承不一样,这个只是配置的继承。
<bean abstract="true" id="common">
<property name="province" value="广东"></property>
</bean>
<bean class="cn.itouchtv.Address" id="address" parent="common">
<property name="city" value="广州" > </property>
</bean>
对于配置的继承,比如上述的common,这个bean可以是抽象的和shili的,还可以没有class属性,也可以有。当引用这个配置的bean时,使用parent属性,此时进行属性的设置,没有的继承,有的则覆盖。