一个人有猫和狗两个宠物
package pojo;
public class Cat {
public void shout() {
System.out.println("喵~");
}
}
Dog.java
package pojo;
public class Dog {
public void shout() {
System.out.println("汪~");
}
}
People.java
package pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
}
beans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
<property name="name" value="zsr"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
bean>
beans>
MyTest.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.People;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
people.getDog().shout();
people.getCat().shout();
System.out.println(people.getName());
}
}
测试:
到此环境搭建成功!
上述代码中,ref
就是寻找对应的cat和dog对象;如果有一种机制,能够自动在bean里面寻找我们要设置的cat或者dog,自动装配,就不用写下面的那两行代码了!这就引入了自动装配
我们更改一下.xml
文件,删除那两行代码,加入autowire
属性,发现有几种可以选择,这里先选择byName
<bean id="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byName">
<property name="name" value="zsr"/>
bean>
再次运行测试类,依旧成功,说明我们的cat和dog被自动设置到了people中
那我们再更改一下,将dog
改为dog1
<bean id="cat" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byName">
<property name="name" value="zsr"/>
bean>
byName
:根据属性名
自动装配,检查IoC容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。
因此bean的id只有为dog
或者cat
才能够被找到
我们再改一下,将byName
改为byType
<bean id="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byType">
<property name="name" value="zsr"/>
bean>
必须保证类型全局唯一,如果多加一个dog,则报错:
可以省略id
<bean class="pojo.Cat"/>
<bean class="pojo.Dog"/>
<bean id="people" class="pojo.People" autowire="byType">
<property name="name" value="zsr"/>
bean>
小结
byName
的时候,需要保证所有bean的id唯一,并且这个bean id需要和实体类中对应的属性名相同byName
的时候,需要保证所有bean的class唯一,并且这个bean id需要和自动注入属性的类型一致;可以省略idjdk1.5支持注解,Spring2.5支持注解
要使用注解:
xml中导入约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
xml中配置注解支持
<context:annotation-config/>
<context:annotation-config/>
<bean id="cat1" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
<property name="name" value="zsr"/>
bean>
运行测试类,成功
自动装配环境很复杂的情况下:假设此时有两个cat和dog对象
<context:annotation-config/>
<bean id="cat1" class="pojo.Cat"/>
<bean id="cat2" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="dog2" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
<property name="name" value="zsr"/>
bean>
发现直接爆红了
这是因为无法匹配到对应的属性,@Autowired 默认通过 byType
的方式实现,如果有多个对象,则通过 byName
查找,如果都找不到,则报错;
此时通过有两个相同类型的对象,通过类型无法找到,bean id也不与属性名相同,通过名字也找不到,所以报错;
这时候就需要配合@Qualifier
来使用,指定唯一的bean对象来注入
再次运行,即可成功
@Qualifier
还可以设置required
属性值为false 允许属性值为null
我们将上述的Autowired
换成Resource
xml文件为:
<context:annotation-config/>
<bean id="cat1" class="pojo.Cat"/>
<bean id="cat2" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="dog2" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
<property name="name" value="zsr"/>
bean>
直接运行
发现报错了,这是因为我们无法匹配到对应的属性,@Resource 默认通过 byName
的方式实现,如果找不到名字, 则通过 byType
实现!如果两个都找不到,就会报错
此时,名字cat1/cat2/dog1/dog2
不匹配,且每个类型的bean不唯一,所以通过名字和类型都找不到,因此报错
如果我们将其中一个bean的id改为对应的属性名cat
和dog
<bean id="cat" class="pojo.Cat"/>
<bean id="cat2" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="dog2" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
<property name="name" value="zsr"/>
bean>
再次运行,成功了
这是因为我们通过名字找到了
我们还有另一种解决方式,不用更改bean的id,我们在@Resource
里面添加name
属性
通过设置name属性指定装配的对象
@Autowired和@Resource的相同点:
属性字段
和set方法
上@Autowired和@Resource的区别:
byType
的方式实现,如果有多个对象,则通过 byName
查找,如果都找不到,则报错;此时可以用@Qualifier指定唯一的bean对象byName
的方式实现,如果找不到名字, 则通过 byType
实现!如果两个都找不到,就会报错