一:自动装配说明
- 自动装配是使用spring满足bean依赖的一种方法 。
- spring会在应用上下文中为某个bean寻找其依赖的bean。
Spring中bean有三种装配机制:
在xml中显式配置;
在java中显式配置;
隐式的bean发现机制和自动装配。
Spring的自动装配需要从两个操作实现:
组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
自动装配(autowiring):spring自动满足bean之间的依赖(IoC/DI);
不推荐使用自动装配xml配置 , 而使用注解
二:xml方式自动装配(不推荐)
实体类:
public class Books {
public void show(){
System.out.println("读四大名著");
}
}
public class Hobbies {
public void show(){
System.out.println("培养兴趣爱好");
}
}
public class Pepole {
private String name;
private Books books;
private Hobbies hobbies;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Books getBooks() {
return books;
}
public void setBooks(Books books) {
this.books = books;
}
public Hobbies getHobbies() {
return hobbies;
}
public void setHobbies(Hobbies hobbies) {
this.hobbies = hobbies;
}
@Override
public String toString() {
return "Pepole{" +
"name='" + name + '\'' +
", books=" + books +
", hobbies=" + hobbies +
'}';
}
}
配置文件:
- autowire byName (按名称自动装配)
byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid(通过id匹配)
<?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="books" class="com.lmy.pojo.Books"/>
<bean id="hobbies" class="com.lmy.pojo.Hobbies"/>
<bean id="pepole" class="com.lmy.pojo.Pepole" autowire="byName">
<property name="name" value="zhangSan"/>
</bean>
</beans>
总结:
当一个bean节点带有 autowire byName的属性时:
将查找其类中所有的set方法名,例如setBooks,获得将set去掉并且首字母小写的字符串,即books。去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常。
- autowire byType (按类型自动装配)
byType : 会自动在容器上下文中查找,和自己对象属性类型相同的bean(通过class匹配)
使用autowire byType首先需要保证:同一类型的bean对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。
<?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="books" class="com.lmy.pojo.Books"/>
<bean id="hobbies" class="com.lmy.pojo.Hobbies"/>
<bean id="pepole" class="com.lmy.pojo.Pepole" autowire="byType">
<property name="name" value="zhangSan"/>
</bean>
</beans>
测试:
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Pepole pepole = context.getBean("pepole", Pepole.class);
pepole.getBooks().show();
pepole.getHobbies().show();
}
}
输出:
读四大名著
培养兴趣爱好
Process finished with exit code 0
结论:
- byname的时候,要保证所有bean的id唯一,且这个bean需要和自动注入的属性的set方法的值一致
- bytype的时候,要保证所有bean的class唯一,且这个bean需要和自动注入的属性的类型一致
二:使用注解
实体类:
public class Books {
public void show(){
System.out.println("读四大名著");
}
}
public class Hobbies {
public void show(){
System.out.println("培养兴趣爱好");
}
}
public class Pepole {
private String name;
@Autowired
@Qualifier("books1")
private Books books;
@Autowired
private Hobbies hobbies;
public Books getBooks() {
return books;
}
public Hobbies getHobbies() {
return hobbies;
}
@Override
public String toString() {
return "Pepole{" +
"name='" + name + '\'' +
", books=" + books +
", hobbies=" + hobbies +
'}';
}
}
配置文件:
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="books2" class="com.lmy.pojo.Books"/>
<bean id="books1" class="com.lmy.pojo.Books"/>
<bean id="hobbies" class="com.lmy.pojo.Hobbies"/>
<bean id="pepole" class="com.lmy.pojo.Pepole"/>
</beans>
注意: 在spring配置文件中引入context文件头
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
开启属性注解支持!
<context:annotation-config/>
测试类:
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Pepole pepole = context.getBean("pepole", Pepole.class);
pepole.getBooks().show();
pepole.getHobbies().show();
}
}
1)使用 @Autowired 自动装配
@Autowired是Spring提供的注解,用于自动装配
装配方式:
- 按类型装配(默认使用的装配方式)。
- 按名称装配(结合@Qualifier注解使用)。
注解属性:
required:默认值true。值为true时,表示必须注入,如bean不存在则会报错;值为false时,表示bean存在就注入,不存在则不注入。
作用范围:@Autowired的作用范围:成员变量、构造器、方法、参数。
- 成员变量
@Service
public class UserService {
@Autowired
private IUser user;
}
- 构造器:构造器上使用Autowired注解,实际上还是使用了成员变量装配的方式,并非构造器装配。
@Service
public class UserService {
private IUser user;
@Autowired
public UserService(IUser user) {
this.user = user;
}
}
- 方法:Spring会在项目启动的过程中,自动调用一次@Autowired注解的方法,我们可以在该方法做一些初始化的工作。
@Service
public class UserService {
@Autowired
public void test(IUser user) {
user.test();
}
}
- 参数:在非静态方法的入参上加Autowired注解
@Service
public class UserService {
public void test(@Autowired IUser user) {
user.test();
}
}
@Qualifier的使用:通过@Autowired和@Qualifier的结合使用可以按名称装配。
@Autowired
@Qualifier("books1")
private Books books;
配置:
<bean id="books2" class="com.lmy.pojo.Books"/>
<bean id="books1" class="com.lmy.pojo.Books"/>
<bean id="hobbies" class="com.lmy.pojo.Hobbies"/>
实体类:
@Autowired
@Qualifier("books1")
private Books books;
@Autowired
private Hobbies hobbies;
输出:
读四大名著
培养兴趣爱好
Process finished with exit code 0
2)使用@Resource自动装配
@Resource是JDK自带的注解,用于自动装配。
@Resource默认按照名称自动注入
-
既没指定name,也没指定type,自动按照名称装配(当注解写在字段上时,默认取字段名,当注解写在setter方法上时,默认取属性名进行装配。);如果没有匹配,则退而按照类型装配,找不到则抛出异常。
-
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
-
如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
-
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
注解属性
Resource注解的主要属性:
- name:指定需注入的bean的名称
- type: 指定需注入的bean的类型
作用范围
@Resource的作用范围:成员变量、方法。
- 成员变量
@Service
public class UserService {
@Resource
private IUser user;
}
- 方法
@Service
public class UserService {
@Resource
public void test(IUser user) {
user.test();
}
}
@Resource指定按type自动装配:
@Resource(type = Books.class)
private Books books;
@Resource指定按name自动装配:
@Resource(name = "books")
private Books books;
@Autowired与@Resource对比: