Spring中Bean的装配方式
Spring有三种装配Bean的方式:
(1)在XML中显式配置;
(2)在Java中显式配置;
(3)隐式的Bean发现机制和自动装配;
之前在xml中设置Bean的属性就是第一种方式,而第三种方式是Spring中最重要的装配方式。
Spring的自动装配需要从两个操作来实现:
组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
组件扫描和自动装配组合发挥巨大威力,使的显示的配置降低到最少。Spring的自动装配分为xml装配和注解,推荐不使用自动装配xml配置 , 而使用注解 。
使用xml配置完成自动装配
package com.wjh.po;/*** @author wjh* @date 2021/7/16 23:13* @Package com.wjh.po*/public class Cat {public void shout(){System.out.println("喵喵喵~~~");}}
package com.wjh.po;/*** @author wjh* @date 2021/7/16 23:12* @Package com.wjh.po*/public class Dog {public void shout(){System.out.println("汪汪汪!!!");}}
package com.wjh.po;/*** @author wjh* @date 2021/7/16 23:14* @Package com.wjh.po*/public class Person {private String name;private Cat cat;private Dog dog;public Person() {}public Person(String name, Cat cat, Dog dog) {this.name = name;this.cat = cat;this.dog = dog;}public String getName() {return name;}public void setName(String name) {this.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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", cat=" + cat +", dog=" + dog +'}';}}
byName自动装配(按名称自动装配)
<bean id="dog" class="com.wjh.po.Dog" /><bean id="cat" class="com.wjh.po.Cat"/><bean id="person" class="com.wjh.po.Person" autowire="byName"><property name="name" value="阿离"/></bean>
可以看到,byName自动装配只需要在bean标签加上“autowire=”byName””即可,这样就可以自动装配Person类的cat(装载为Cat实例)和dog(装载为Dog实例)属性了,而以前的手动装载的xml配置是:
<bean id="dog" class="com.wjh.po.Dog" /><bean id="cat" class="com.wjh.po.Cat"/><bean id="person" class="com.wjh.po.Person" autowire="byName"><property name="name" value="阿离"/><property name="cat" ref="cat"/><property name="dog" ref="dog"/></bean>
byName实现机制:
byName自动装配是利用Java的反射机制获取自动装配类中的set方法名,去掉set后将其首字母小写再到IOC容器中查找是否有对应Bean的id,如果有则查看该Bean的类型与set方法的参数类型是否匹配,匹配上了则调用set方法进行依赖注入,否则会报空指针异常。因此,byName的自动装配跟set方法名和参数类型有关,跟属性名无关。
byType自动装配 (按类型自动装配)
使用byType自动装配的前提条件:同一类型的对象,在spring容器中唯一。如果不满足前提条件会报不唯一异常(NoUniqueBeanDefinitionException)。如(不满足前提,无法自动装配):
<bean id="dog" class="com.wjh.po.Dog" /><bean id="cat" class="com.wjh.po.Cat"/><bean id="cat2" class="com.wjh.po.Cat"/><bean id="person" class="com.wjh.po.Person" autowire="byType"><property name="name" value="阿离"/></bean>
byType实现机制:
byType自动装配是利用Java的反射机制获取类中的set方法的参数类型,寻找此接口类型的实现类或子类,找到后将其首字母小写与IOC容器Bean的id进行匹配,匹配成功后则调用set方法进行依赖注入。因此,byType自动装配与方法名无关,与属性名无关,与set方法的参数类型有关。
通过byName和byType的实现机制可以看到,二者都用到的是反射机制,而且都必须具有set方法,否则无法完成装配。
使用注解完成自动装配
环境配置:
<?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 https://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/>//开启属性注解支持<bean id="..." name="...">...<bean/></beans>
使用@Autowired自动装配
@Autowired可以想象成byType装配,只需要在属性上面打上这个注解就可以完成自动装配了,如:
package com.wjh.po;import org.springframework.beans.factory.annotation.Autowired;/*** @author wjh* @date 2021/7/16 23:14* @Package com.wjh.po*/public class Person {private String name;@Autowiredprivate Cat cat;@Autowiredprivate Dog dog;public Person() {}public Person(String name, Cat cat, Dog dog) {this.name = name;this.cat = cat;this.dog = dog;}public String getName() {return name;}public void setName(String name) {this.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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", cat=" + cat +", dog=" + dog +'}';}}
注意事项
(1)@Autowired注解和byType装载不同的是,去掉set方法依然可以完成自动装配,由于@Autowired注解实现原理较为复杂,暂时不做解释。
(2)@Autowired注解可以配合@Qualififier使用,@Qualififier注解是根据类型(byName)自动装配的,如:
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
但是@Qualififier注解是不能够单独使用的。
(3)@Autowired(required=false) 表示的是它注解的属性可以为null,但required的默认值是true。
使用@Resource自动装配
@Resource注解中如有指定的name属性,先按name属性执行的值进行byName方式查找装配;其次再进行默认的byName方式(获取自动装配类中的set方法名,去掉set后将其首字母小写)进行装配;如果以上都不成功,则按byType的方式自动装配,如果还是不成功,则报异常。如:
@Resource(name = "cat")
private Cat cat;
@Resource
private Dog dog;
