Spring中bean的自动装配
spring中可以实现bean的自动装配,这样我们就可以简化许多代码,且提高代码的精确度,避免手写引发的代码错误。
spring中bean的自动装配有两种实现情况
- xml
- 注解
使用xml来实现bean的自动装配
使用xml来实现bean的自动装配主要还是依靠bean标签中autowire属性
autowire主要存在两个值:byName和byType,分别依据不同的条件来自动装配
实体类1:
public class Friend1 {
public void shout() {
System.out.println("孙笑川");
}
}
实体类2:
public class Friend2 {
public void shout() {
System.out.println("韩金龙");
}
}
用户类(关联两个实体类):
@lombok
public class master {
private Frined1 f1;
private Frined2 f2;
private String name;
}
}
byName(按名称自动装配)
byName(按名称自动装配)的机制就是spring去寻找主类中所有的set方法名,当找到set后面的字符和xml中bean的id相符时,就会自动配对。
例如setFriend1,获得将set去掉并且首字母小写的字符串,即friend1。
<?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="friedn1" class="com.nicht.pojo.Friend1"/>
<bean id="friedn2" class="com.nicht.pojo.Friend2"/>
<bean id="master" class="com.nicht.pojo.master" autowire="byName">
<property name="name" value="候国玉"/>
</bean>
</beans>
但当相对应的Bean id 和set方法后的字符小写不对应时就会报空指针java.lang.NullPointerException的错误
byType (按类型自动装配)
byType(按类型自动装配)的机制是依靠bean中class所标记的路径对象
所以byType的情况下,id可以不同,乃至id都不写
但在spring容器class的路径对象必须是唯一,不能有重复的
<?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 class="com.nicht.pojo.Friend1"/>
<bean class="com.nicht.pojo.Friend2"/>
<bean id="master" class="com.nicht.pojo.master" autowire="byType">
<property name="name" value="候国玉"/>
</bean>
</beans>
但当相对应的Spring容器中拥有重复的class路径对象就会报不唯一的异常NoUniqueBeanDefinitionException
使用注解来实现bean的自动装配
利用注解来实现bean的自动装配主要依靠
- @Autowired
- @Qualifier
- @Resource
三个注解关键词。Spring要想使用注解的自动装配的话,还需要在spring配置中引入context头文件和约束。
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context/spring-context.xsd
且开启属性注解支持
<context:annotation-config/>
@Autowired
使用**@Autowired** 就可以把实体类中的set方法去掉,用**@Autowired代替来代替set方法**。
且 @Autowired是按 类型(Type)自动转配的,不支持id匹配。
所以spring容器中存在重复的class路径对象也会报错
使用@Autowired需要导入 spring-aop包
实体类:
public class master {
@Autowired
private Frined1 f1;
@Autowired
private Frined2 f2;
private String name;
public Frined1 getFrined1() {
return f1;
}
public Frined2 getFrined2() {
return f3;
}
public String getName() {
return name;
}
public String setName(String name) {
this.name = name;
}
}
}
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"
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="friend1" class="com.nicht.pojo.Friend1"/>
<bean id="friend2" class="com.nicht.pojo.Friend2"/>
<bean id="master" class="com.nicht.pojo.master"/>
<property name="name" value="候国玉"/>
</bean>
用到注解开发时,也就不需要属性autowride来进行配置
如果在实体类中有属性允许为null的话,可以在 @Autowride 中设置。
设置 required = false ,默认为true
@Autowired(required = false)
false,对象可以为null;true,对象必须存对象,不能为null。
@Qualifier
@Qualifier不能单独使用 必须配合 @Autowried
@Autowired是根据类型自动装配的,加上 @Qualifier 则可以根据byName的方式自动装配
实体类:
public class master {
@Autowired
@Qualifier(value = "frined1")
private Frined1 f1;
@Autowired
@Qualifier(value = "friend2")
private Frined2 f2;
private String name;
public Frined1 getFrined1() {
return f1;
}
public Frined2 getFrined2() {
return f3;
}
public String getName() {
return name;
}
public String setName(String name) {
this.name = name;
}
}
}
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"
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/>
<!-- 如果没有添加Qualifier来确定id,则会报错-->
<bean id="friend1" class="com.nicht.pojo.Friend1"/>
<bean id="friend11" class="com.nicht.pojo.Friend1"/>
<bean id="friend2" class="com.nicht.pojo.Friend2"/>
<bean id="friend22" class="com.nicht.pojo.Friend2"/>
<bean id="master" class="com.nicht.pojo.master"/>
<property name="name" value="候国玉"/>
</bean>
@Resource
@Resource的作用和 @Autowried作用大同小异,但 @Resource若要进行名称自动装配的情况时,不需要添加@Qualifier
@Resource的运行顺序:
- @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
- 其次再进行默认的byName方式进行装配;(默认的byName一般为属性类型小写)
- 如果以上都不成功,则按byType的方式自动装配
- 都不成功,则报异常。
实体类:
public class master {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "friend11")
private Friend1 friend1;
@Resource
private Friend2 friend2;
private String name;
}
spring配置:
因为friend1有指定name参数,所以走了byName
但friend2没有指定,所以走了默认byName也就是去寻找了friend2
如果byName也没找到的话,就会靠byType去寻找相对应的class,如果有重复那么就报错。
<bean id="friend1" class="com.nicht.pojo.Friend1"/>
<bean id="friend11" class="com.nicht.pojo.Friend1"/>
<bean id="friend2" class="com.nicht.pojo.Friend2"/>
<bean id="friend22" class="com.nicht.pojo.Friend2"/>
<bean id="master" class="com.nicht.pojo.master"/>
<property name="name" value="候国玉"/>
</bean>