- 自动装配是Spring满足bean依赖一种方式
- Spring会在上下文中自动寻找, 并自动给bean装配属性
在Spring中有三种装配的方式
-
在xml中显示的配置
-
在java中显示配置
-
隐式的自动装配bean [重要]
1. 测试
1. 环境搭建 -- 一个人有两个宠物
pojo实体类
Cat
package com.jean.pojo;
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
Dog
package com.jean.pojo;
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
People
package com.jean.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public People() {
}
public People(Cat cat, Dog dog, String name) {
this.cat = cat;
this.dog = dog;
this.name = name;
}
}
resource
beans.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"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="cat" class="com.jean.pojo.Cat"/>
<bean id="dog" class="com.jean.pojo.Dog"/>
<bean id="people" class="com.jean.pojo.People">
<property name="name" value="张泽熙"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>
</beans>
测试类
import com.jean.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
// 让狗🐕叫
System.out.print("让狗🐕叫");
people.getDog().shout();
// 让猫🐱叫
System.out.print("让猫🐱叫");
people.getCat().shout();
}
}
2. ByName自动装配
我们之前是手动引入
现在使用 autowire=“byName” 就可以实现自动装配
它的原理是:
byName: 会自动在容器上下文中查找, 和自己对象set方法后面的值对应的beanid;
<?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:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="cat" class="com.jean.pojo.Cat"/>
<bean id="dog" class="com.jean.pojo.Dog"/>
<!--
byName: 会自动装配在容器上下文中查找, 和自己对象set方法后面的值对应 beanId;
-->
<bean id="people" class="com.jean.pojo.People" autowire="byName">
<property name="name" value="张泽熙"/>
<!-- <property name="dog" ref="dog"/>-->
<!-- <property name="cat" ref="cat"/>-->
</bean>
</beans>
此时byName就去自动查找我们People实体类下的set方法后面的值对应的beanid[cat/dog]:
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
如果把beans.xml里Dog注册的名字改为dog222他就找不到了, 因为我们Set方法后没有对应的dog222的方法值
<?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:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="cat" class="com.jean.pojo.Cat"/>
<!-- <bean id="dog" class="com.jean.pojo.Dog"/>-->
<bean id="dog222" class="com.jean.pojo.Dog"/>
<!--
byName: 会自动装配在容器上下文中查找, 和自己对象set方法后面的值对应 beanId;
-->
<bean id="people" class="com.jean.pojo.People" autowire="byName">
<property name="name" value="张泽熙"/>
<!-- <property name="dog" ref="dog"/>-->
<!-- <property name="cat" ref="cat"/>-->
</bean>
</beans>
3. byType自动装配
如我们把 autowire=“byName” 改为: autowire=“byType”
<?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:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="cat" class="com.jean.pojo.Cat"/>
<!-- <bean id="dog" class="com.jean.pojo.Dog"/>-->
<bean id="dog222" class="com.jean.pojo.Dog"/>
<!--
byName: 会自动装配在容器上下文中查找, 和自己对象set方法后面的值对应 beanId;
-->
<bean id="people" class="com.jean.pojo.People" autowire="byName">
<property name="name" value="张泽熙"/>
<!-- <property name="dog" ref="dog"/>-->
<!-- <property name="cat" ref="cat"/>-->
</bean>
</beans>
我们Dog id写为dog222就可以找到…? 那么这是为什么呢?
刚才byName不行byType就可以了呢?
因为:
byType: 会自动在容器上下文中查找, 和自己对象属性类型相同的bean
当然byType也有自己的弊端它需要保持自己的全局唯一, 如:
beans.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"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean id="cat" class="com.jean.pojo.Cat"/>
<bean id="dog" class="com.jean.pojo.Dog"/>
<bean id="dog222" class="com.jean.pojo.Dog"/>
<!--
byName: 会自动装配在容器上下文中查找, 和自己对象set方法后面的值对应 beanId;
-->
<bean id="people" class="com.jean.pojo.People" autowire="byType">
<property name="name" value="张泽熙"/>
<!-- <property name="dog" ref="dog"/>-->
<!-- <property name="cat" ref="cat"/>-->
</bean>
</beans>
我们配置了两个Dog测试它直接就会报错, 不会帮你跑
byType必须保证它的类型全局唯一才可以自动装配
那如果我们把id直接去掉省略掉我们就可以使用byType测试跑起来了
比如:
<?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:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
https://www.springframework.org/schema/lang/spring-lang.xsd">
<bean class="com.jean.pojo.Cat"/>
<bean class="com.jean.pojo.Dog"/>
<!--
byName: 会自动装配在容器上下文中查找, 和自己对象set方法后面的值对应 beanId;
-->
<bean id="people" class="com.jean.pojo.People" autowire="byType">
<property name="name" value="张泽熙"/>
<!-- <property name="dog" ref="dog"/>-->
<!-- <property name="cat" ref="cat"/>-->
</bean>
</beans>
甚至不用给他命名字, 也可以使用type找到, 因为它是根据类型来的
自动装配基于上下文来的
小结:
- byName的时候,需要保证所有bean的id唯一, 并且这个bean需要和自动注入的属性的set方法的值一致.
- byType的时候,需要保证所有bean的class唯一, 并且这个bean需要和自动注入的属性类型一致.