和自动装配相对应的就是手动装配,在讲自动装配前先介绍手动装配,就是要自己给定属性,然后赋值
1. 手动装配
1.1 使用场景
有一个Person
类,这个类中聚合了一个Cat
类和Dog
类。
public class Person {
private Dog dog;
private Cat cat;
private String name;
// getter/setter...
}
那么在xml中我们要这样写:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="com.zzw.pojo.Cat" />
<bean id="dog" class="com.zzw.pojo.Dog" />
<bean id="people" class="com.zzw.pojo.Person">
<property name="name" value="Bob" />
<property name="cat" ref="cat" />
<property name="dog" ref="dog" />
</bean>
</beans>
1.2 缺点
可以看到所谓手动注入是指在xml中采用硬编码的方式来配置注入的对象,比如通过构造器注入或者set方法注入,这些注入的方式都存在不足:
- 如果需要注入的对象比较多,比如
Person
类中有几十个属性,那么上面的property属性是不是需要写几十个,此时配置文件代码量暴增 - 如果
Person
类中新增或者删除了一些依赖,还需要手动去调整bean xml中的依赖配置信息,否则会报错 - 总的来说就是不利于维护和扩展
2. 自动装配
自动装配的意义和p/c命名空间的使用一样,为了简化代码。自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。
自动装配方式:1. byType 2. byName 3. constructor 4. default
<bean id="" class="" autowire="byType|byName|constructor|default" />
2.1 ByName自动装配
给bean添加一个属性autowire="byName"
<bean id="cat" class="com.zzw.pojo.Cat" />
<bean id="dog" class="com.zzw.pojo.Dog" />
<bean id="people" class="com.zzw.pojo.Person" autowire="byName">
<!-- 使用autowire之后,就无需再为Person装配Cat和Dog属性 -->
<property name="name" value="Bob" />
</bean>
2.1.1 注意点
- 保证所有bean的id唯一
- 在容器上下文寻找,对象set方法后面的值必须和对应的beanid一样,即
Dog
的bean id必须是dog
,因为Person
里的setDog()
里是"Dog",换成小写就是"dog"。 - 未找到对应名称的bean对象则set方法不进行注入,并不会报错(如果报了可能是因为测试代码中用到了注入失败的bean对象)
2.2 ByType自动装配
给bean添加一个属性autowire="byType"
<bean id="cat" class="com.zzw.pojo.Cat" />
<bean class="com.zzw.pojo.Dog" />
<bean id="people" class="com.zzw.pojo.Person" autowire="byType">
<property name="name" value="Bob" />
</bean>
2.2.1 注意点
- 保证所有bean的class唯一!按照类型自动装配的时候,如果按照类型找到了多个符合条件的bean,系统会报错。
- 在容器上下文寻找,对象set方法的类型必须和对应的bean的类型一样
- 使用ByType,bean可以没有
id
3. 使用注解实现自动装配
大部分情况下,都会使用注解进行开发而非xml,因为xml还是太麻烦了。
使用注解:
- 导入约束:
xmlns:context="http://www.springframework.org/schema/context"
- 配置注解的支持:
<context:annotation-config/>
<?xml version="1.0" encoding="UTF-8"?>
<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">
<context:annotation-config/>
</beans>
@Autowire
,直接在属性上使用即可,也可以在set
方法上使用。对属性使用了@Autowire
后,set
方法都可以直接省略(反射机制),但get方法还是要写,前提是:这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byName。
@Autowire
默认先使用byType,不匹配再使用byName。
Java代码:
public class Person {
@Autowired // 使用该注解后,会自动去Spring的IOC容器中寻找相应"类型"的已被注册的bean
private Dog dog;
@Autowired
private Cat cat;
private String name;
...
}
beans.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">
<context:annotation-config/>
<bean id="cat" class="com.zzw.pojo.Cat" />
<bean id="dog" class="com.zzw.pojo.Dog" />
<bean id="people" class="com.zzw.pojo.Person" />
</beans>
测试代码:
public class MyTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person people = applicationContext.getBean("people", Person.class);
people.getCat().shout();
people.getDog().shout();
}
}
4. @Qualifier
@Qualifier
,可以指定字段在xml配置文件中的id,当xml中有多个同一对象(有着不同id),这个注解比较好用。换言之,这是类型重复了,使用@Qualifier
来指定是一个具体bean的id。@Qualifier
注解通常和@Autowire
一同使用。
Bean:
public class Person {
@Autowired
private Dog dog;
@Autowired
@Qualifier(value = "cat123")
private Cat cat;
private String name;
...
}
beans.xml文件:
<bean id="cat" class="com.zzw.pojo.Cat" />
<bean id="dog" class="com.zzw.pojo.Dog" />
<bean id="cat123" class="com.zzw.pojo.Cat" />
<bean id="people" class="com.zzw.pojo.Person" />
注意:
@Qualifier
相对应的类型必须匹配
5. @Resource
@Resource
,Java的注解,效果和@Aotuwire
类似,默认byName
和byType
。这个注解使用频率低,主要还是@Autowire
。