Spring 自动化装配 Bean

Spring 从两个角度来实现自动化装配:

  • 组件扫描:Spring 会自动发现应用上下文中所创建的 bean。
  • 自动装配:Spring 会自动满足 bean 之间的依赖关系。

组件

Spring 中使用 @Component 注解将一个类标注为组件类,并告知 Spring 要为这个类创建 bean,这样就不用显式配置了。代码如下: 首先,我们创建一个 CompactDisc 接口

java 复制代码
package org.example.autoconfig;

public interface CompactDisc {
	void play();
}

然后,创建一个 CompactDisc 接口的实现类 SgtPeppers,并使用 @Component 注解将该类标注为一个组件类。

java 复制代码
package org.example.autoconfig;

import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {
    private String title = "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";
    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

Spring 应用上下文会为所有的 bean 创建一个 ID,默认值就是类名的首字母小写。如果想要为 bean 设置 ID 值,只需要在 @Component 注解中传入 ID 的值即可。例如:

java 复制代码
package org.example.autoconfig;

import org.springframework.stereotype.Component;

// 设置 SgtPeppers 类的 bean 的 ID 为 lonelyHeartsClub
@Component("lonelyHeartsClub") 
public class SgtPeppers implements CompactDisc {
    ...
}

组件扫描

Spring 的组件扫描默认是不开启的,需要显式地配置,从而 命令 Spring 去寻找带有 @Component 注解的类。有两种方式开启组件扫描。

  1. 在配置类(@Configuration 注解标注的类)中使用 @ComponentScan 注解,开启组件扫描。 @ComponentScan 默认会扫描与配置类相同的包以及这个包下的所有子包,带有 @Component 注解的类,并自动为其创建一个 bean。代码如下:
java 复制代码
package org.example.autoconfig;

@Configuration
@ComponentScan
public class CDPlayerConfig {
	...
}

如果想扫描指定的包,可以在 @ComponentScan 注解的 value 属性中,使用 String 类型的值指明包名称:

java 复制代码
package org.example.autoconfig;

@Configuration
@ComponentScan("org.example.autoconfig")
public class CDPlayerConfig {
	...
}

如果想要更加清晰地表明设置的是基础包,可以通过 basePackages 属性进行设置,可以设置一个或者多个基础包:

java 复制代码
package org.example.autoconfig;

@Configuration
// 设置一个基础包
@ComponentScan(basePackages = "org.example.autoconfig")
// 设置多个基础包
// @ComponentScan(basePackages = {"org.example.autoconfig", "org.example.xmlconfig"})
public class CDPlayerConfig {
}

除了使用字符串设置包名称外,还可以将 basePackageClasses 属性设置为包中所包含的类或者接口,这些类所在的包将会作为组件扫描的基础包。

java 复制代码
@Configuration
@ComponentScan(basePackageClasses = { CompactDisc.class, SgtPeppers.class})
public class CDPlayerConfig {
}
  1. 在 Spring 的 XML 配置文件中使用 <context:component-scan> 元素,开启组件扫描。这需要引入 Spring 的 context 命名空间。代码如下:
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 
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd">
       
	<!-- 开启组件扫描, 并指定扫描的基础包为 soundsystem -->
    <context:component-scan base-package="soundsystem"/>
</beans>

自动装配

简单来说,自动装配就是让 Spring 自动满足 bean 依赖的一种方法,在满足依赖的过程中,会在 Spring 应用上下文中寻找匹配某个 bean 需求的其他 bean。为了声明要进行自动装配,可以使用 Spring 的 @Autowired 注解。 首先,先声明一个 MediaPlayer 接口,代码如下:

java 复制代码
package org.example.javaconfig;

public interface MediaPlayer {
    void play();
}

然后,在它的实现类的构造函数上使用 @autowired 注解,当 Spring 创建 CDPlayer 类的 bean 的时候,会通过这个构造器来进行实例化并且传入一个 CompactDisc 类的 bean,实现自动装配,代码如下:

java 复制代码
package org.example.javaconfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc cd;

    // 使用在构造函数上,当Spring要创建CDPlayer的bean时,会自动注入CompactDisc的bean
    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd = cd;
    }
    @Override
    public void play() {
        cd.play();
    }
}

@Autowired 注解不仅能够用在构造器上,还能在属性的 Setter 方法上,如果 CDPlayer 类有一个 setCompactDisc() 方法,可以采用下面的注解形式进行自动装配:

java 复制代码
@Autowired
public void setCompactDisc(CompactDisc cd){
	this.cd = cd;
}

在 Spring 初始化 bean 之后,它会尽可能的去满足 bean 的依赖。不管是构造器、Setter 方法还是其他的方法,Spring 都会尝试满足方法参数上所声明的依赖。假如有且只有一个 bean 匹配依赖需求的话,那么这个 bean 将会被装配进来。 如果没有匹配的 bean,那么在应用上下文创建的时候,Spring 会抛出一个异常。为了避免异常的出现,可以将 @Autowired 的 required 属性设置为 false:

java 复制代码
@Autowired(required=false)
public CDPlayer(CompactDisc cd){
	this.cd = cd;
}

将 required 属性设置为 false 时,Spring 会尝试执行自动装配,但是如果没有匹配的 bean 的话,Spring 将会让这个 bean 处于未装配状态。但是,把 required 属性设置为 false 时,需要谨慎对待。如果在代码中没有进行 null 检查的话,这个处于未装配状态的属性有可能会出现 NullPointerException。 如果有多个 bean 都能满足依赖的话,Spring 将会抛出一个异常,表明没有明确指定要选择哪个 bean 进行自动装配。

相关推荐
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭28 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
李小白661 小时前
Spring MVC(上)
java·spring·mvc
Lojarro3 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
zjw_rp4 小时前
Spring-AOP
java·后端·spring·spring-aop
撒呼呼7 小时前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
天使day8 小时前
SpringMVC
java·spring·java-ee
壹佰大多9 小时前
【spring-cloud-gateway总结】
java·spring·gateway
CodeChampion9 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
秋意钟10 小时前
Spring框架处理时间类型格式
java·后端·spring
科马13 小时前
【Redis】缓存
数据库·redis·spring·缓存