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 进行自动装配。

相关推荐
Flittly21 小时前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
唐青枫5 天前
Java Spring WebFlux 实战指南:用 Mono、Flux 和 WebClient 写响应式接口
java·spring
咖啡八杯6 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
Flittly8 天前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
dunky8 天前
Spring 的三级缓存与循环依赖
后端·spring
码云数智-园园13 天前
C++20 Modules 模块详解
java·开发语言·spring
咖啡八杯13 天前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
Flittly13 天前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring
李少兄13 天前
从原理到实战:Spring IoC/DI 核心知识体系与高频面试题全解
java·后端·spring
shushangyun_13 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化