一、Bean 的自动装配
-
在Spring中有三种装配的方式:
- 在xml中显式的配置:手动配置
- 在java中显式配置:Java 代码配置
- 隐式的自动装配bean【重要】:Bean 的自动装配
在Spring框架中,Bean的自动装配是一种便捷的方式,用于将依赖关系自动注入到Bean中。通过自动装配,Spring可以根据一些规则自动将合适的Bean注入到其他Bean中,从而简化了开发过程。
-
Spring 提供的自动装配方式
- 在配置文件 Bean.xml 中使用< bean >标签的 autowire 属性来指定自动装配的方式。例如,使用autowire="byName"来进行byName方式的自动装配。
-
Spring 提供的自动装配选项:
-
byName :byName 方式是根据 Bean 的名称进行装配
- 代码示例
-
实体类:Cat 、Dog、People
public class Cat { public void cry(){ System.out.println("喵"); } }
public class Dog { public void cry(){ System.out.println("汪"); } }
public class People { private Cat cat; private Dog dog; private String 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;} @Override public String toString() { return "People{" + "cat=" + cat + ", dog=" + dog + ", name='" + name + '\'' + '}'; } }
-
Beans.sml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.sys.dto.Cat"/> <bean id="dog" class="com.sys.dto.Dog"/> <!-- 通过 autowire 属性指定 byName 自动装配方式--> <!-- byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的 bean id! 注:需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致。否则会注入失败! --> <bean id="people" class="com.sys.dto.People" autowire="byName"> <property name="name" value="姚青"/> </bean> </beans>
-
测试类
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); People people = (People) context.getBean("people"); people.getCat().cry(); people.getDog().cry(); } }
-
测试结果:注入成功结果,以及 Bean 指定的 id 和实体类属性名不一致失败的结果
-
- 代码示例
-
byType :byType 方式是根据 Bean 的类型进行装配
-
代码示例:实体类、测试类不变,修改Beans.sml
-
Beans.sml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.sys.dto.Cat"/> <bean id="dog" class="com.sys.dto.Dog"/> <!-- 通过 autowire 属性指定 byType 自动装配方式--> <!-- byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean! 注:需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致! --> <bean id="people" class="com.sys.dto.People" autowire="byType"> <property name="name" value="姚青"/> </bean> </beans>
-
测试结果
当类型不唯一时,会提示报错
运行报错:No qualifying bean of type ‘com.sys.dto.Dog’ available: expected single matching bean but found 2: dog,dog2
-
-
-
-
扩展
-
constructor :constructor 方式是通过构造函数进行装配
-
autodetect :autodetect 方式是根据 byType 和 constructor 两种方式进行自动装配
-
二、通过注解实现 Bean 的自动装配
在通过 autowire 属性配置 Bean 的自动装配时,可能会存在漏配的情况,所以在 Spring 推出了使用注解实现 Bean 的自动装配。
注:在JDK 1.5 版本和 Spring 2.5 版本之后就支持注解开发了。
-
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: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>
2.1 @Autowired
-
@Autowired :@Autowired 详细解释
-
@Autowired 可以直接作用在字段属性上,也可以在 set() 上,效果是一样的,但是放在字段属性上时,可以省略 set() 方法。
-
@Autowired 的属性:required
-
required = true:注入 bean 的时候该 bean 必须存在,不然就会注入失败!
-
required = false:注入 bean 的时候如果 bean 存在,就注入成功,如果没有就忽略跳过,启动不会报错!但是不能直接使用,因为该 Bean 为 NULL!
-
-
搭配 @Autowired 使用的注解:@Qualifier
- 因为 @Autowired 的自动装配装配方式是 byType,所以当同一种类型有多个 Bean ,并且 Bean 的 id 还和字段属性名不一致时,会出现无法匹配 Bean 的情况,这种时候就需要使用 @Qualifier(value = “xxx”) 去配置 @Autowired 的使用,指定一个唯一的bean对象注入!
- 因为 @Autowired 的自动装配装配方式是 byType,所以当同一种类型有多个 Bean ,并且 Bean 的 id 还和字段属性名不一致时,会出现无法匹配 Bean 的情况,这种时候就需要使用 @Qualifier(value = “xxx”) 去配置 @Autowired 的使用,指定一个唯一的bean对象注入!
-
- 代码示例
-
改造 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: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="cat22" class="com.sys.dto.Cat"/> <bean id="cat33" class="com.sys.dto.Cat"/> <bean id="dog33" class="com.sys.dto.Dog"/> <bean id="people" class="com.sys.dto.People"> <property name="name" value="姚青"/> </bean> </beans>
-
改造 People 实体类,在cat、dog属性上添加 @Autowired 注解,并删除对应的 set()
public class People { @Autowired @Qualifier(value = "cat22")//指定唯一的 Bean private Cat cat; @Autowired(required = false) // required = false时,允许注入的对象为空,否则不允许 private Dog dog; private String name; public Cat getCat() {return cat;} public Dog getDog() {return dog;} public String getName() {return name;} public void setName(String name) {this.name = name;} @Override public String toString() { return "People{" + "cat=" + cat + ", dog=" + dog + ", name='" + name + '\'' + '}'; } }
-
其余代码不变,运行结果
-
2.2 @Resource
@Resource注解,用于标记字段或方法,以便进行依赖注入。它与@Autowired注解类似,但功能略有不同。
-
@Resource注解有两种用法:
-
标记字段:当@Resource注解标记在字段上时,它会告诉容器需要找到一个与字段名称相匹配的依赖项,并把 Bean 注入到字段给当中。容器将尝试按照名称来匹配依赖项,默认情况下,它将使用字段名作为依赖项的名称。如果找不到符合名称的匹配项,会继续匹配字段的类型,如果都没有匹配项,会抛出异常。
- 代码示例:
java public class MyClass { @Resource private MyDependency myDependency; }
- 代码示例:
-
标记方法:当@Resource注解标记在方法上时,它会告诉容器要调用该方法,并将一个匹配的依赖项作为参数传递给该方法。类似字段的用法,默认情况下,它将使用方法名作为依赖项的名称。
-
代码示例:
@Resource public void setMyDependency(MyDependency myDependency) { this.myDependency = myDependency; }
-
-
-
@Resource注解还有一些可选属性,可以进一步指定依赖项的名称、类型和查找方式。例如:
- name:指定依赖项的名称,用于与容器中的名称进行匹配。
- type:指定依赖项的类型,用于与容器中的类型进行匹配。
- lookup:指定依赖项的JNDI名称,用于在JNDI命名服务中查找依赖项。
2.3 @Resource 和 @Autowired的区别
相同点:
- 都是用来自动装配的,都可以放在属性字段
不同点:
-
@Autowired通过byType的方式实现,而且必须要求这个对象存在!【常用】
-
@Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】
-
执行顺序不同:@Autowired通过byType的方式实现。
-
@Autowired是Spring框架的注解,而@Resource是Java的注解,前者不引用Spring无法使用,后者只要jdk版本是1.5版本以上就可以使用。