隐式的bean发现机制和自动装配

本文介绍Spring框架中的自动装配机制,包括组件扫描、自动装配的过程及如何处理歧义性等问题。通过实例演示了如何利用@Component注解定义组件,@Configuration和@ComponentScan进行配置,以及@Autowired实现依赖注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring装配bean

创建应用对象之间的协作关系的行为通常称为装配,是依赖注入(DI)的本质。

依赖注入很好理解。这里可以简单了解一下:https://blog.youkuaiyun.com/yuanyuan214365/article/details/52900414

Spring具有非常大的灵活性,它提供了三种主要的装配机制:
1、隐式的bean发现机制和自动装配
2、在Java中进行显示配置
3、在XML中进行显示配置

推荐尽可能地使用自动配置的机制,显示配置越少越好。

但是当你必须要显示配置bean的时候(例如源码并非你维护,而你必须为这些代码配置bean),推荐使用比XML更加强大的JavaConfig。最后只有当你想要使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,才应该使用XML。

隐式的bean发现机制和自动装配

Spring从两个角度来实现自动化装配:
组建扫描:自动发现应用上下文中所创建的bean
自动装配:自动满足bean之间的依赖

1、创建可被发现的bean

随便假设这三个:车轮,座位,引擎。是车类需要依靠的组件,每个类各自有自己的方法。

@Component
class Wheel {
    public void roll(){
        System.out.println("Wheels are rolling.");
    }
}

@Component
class Seat {
    public void seat(){
        System.out.println("People sitting in the seats.");
    }
}

@Component
class Engine {
    public void start(){
        System.out.println("Engine start.");
    }
}

这里注意要有@Component注解,这个注解表明该类会作为组件类,并告知Spring要为这个类创建bean。因为有了这个注解,Spring会为你把配置bean的事情处理妥当。

现在组件有了,还需要一件东西要去取寻找组件。

2、创建组件扫描配置类

这个很简单,只需要两个注解。

@Configuration
@ComponentScan
class Config {
}

@Configuration注解表示是配置类,@ComponentScan注解能够在Spring中启用组件扫描,Spring会查找带有@Component注解的类,并会在Spring中自动为其创建一个bean。

@ComponentScan(“packagename”)如果是这样的注解,Spring将会在packagename包中扫描组件,如果没有参数,则将会在配置类的包中扫描。

3、自动装配

interface Transportation {
    void run();
    void stop();
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=Config.class)
public class Car implements Transportation {
    @Autowired
    private Wheel wheel;

    @Autowired
    private Seat seat;

    @Autowired
    private Engine engine;

    @Test
    public void run() {
        seat.seat();
        engine.start();
        wheel.roll();
        System.out.println("The car has run.");
    }

    @Test
    public void stop() {
        System.out.println("Now, the car has stopped.");
    }
}

返回结果:

People sitting in the seats.
Engine start.
Wheels are rolling.
The car has run.
Now, the car has stopped.

@ContextConfiguration(classes=Config.class)表明了配置类的所在,这个Car类将会从Config配置类中获得扫描到的组件,然后通过@Autowired注解自动匹配,将bean注入给各个属性。

@RunWith(SpringJUnit4ClassRunner.class)会在测试开始的时候自动创建Spring的应用上下文,用于单元测试,而不需要一次次繁杂的启动整个容器。(需要有相关环境,具体百度junit4)

大体就是这样了,也不需要XML,只用java code,是非常方便也是非常推荐的方式。

4、处理歧义性

@Autowired固然强大,但是如果有不止有一个bean能否匹配的话,就会阻碍自动装配。

有两种方式处理:
1、表示首选的bean:只需要在组件类前面加一个@Primary注解即可,这样如果有多个bean匹配,就会先注入此组建类。
2、限定自动装配的bean:@Qualifier(“beanid”)注解

@Component
@Qualifier("cold")
class IceCream implements Dessert{
	//code
}

@Component
@Qualifier("crispy")
class Cookies implements Dessert{
	//code
}

@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert){
	this.dessert = dessert;//这里就会将IceCream注入进来
}

@Bean//也可以在显式装配Bean时使用
@Qualifier("crispy")
public Cookie cookie(){
	return new Cookie();
}

可以有多个@Qualifier注解来筛选出特定的一个bean,不过同一条目上重复出现相同类型的多个注解,得要再加一个@Repeatable注解(Java8后可用)。

<think>好的,用户想了解依赖注入自动装配是什么。首先,我需要确认这两个概念在软件工程中的定义应用场景。依赖注入(Dependency Injection,DI)是一种设计模式,用来实现控制反转(Inversion of Control,IoC),目的是减少代码之间的耦合。而自动装配(Autowiring)是依赖注入的一种实现方,通常由框架自动处理依赖关系。 接下来,我应该从基础开始解释,确保用户理解核心概念。比如,依赖注入的三种方:构造函数注入、Setter方法注入接口注入。需要举例子说明,这样用户更容易理解。例如,假设有一个类A依赖于类B,通过构造函数将B的实例传递给A,而不是在A内部直接创建B的实例。 然后,自动装配部分需要说明框架如何自动识别注入依赖,比如Spring框架中的@Autowired注解。这里可能需要提到不同的自动装配策略,如byType、byName等,以及它们之间的区别。 同时,用户可能想知道两者的区别联系。依赖注入是更广泛的概念,而自动装配是实现依赖注入的一种技术手段。需要强调自动装配带来的便利,比如减少手动配置,但也可能带来潜在的问题,比如多个匹配时的歧义性。 还要考虑用户可能的疑问,比如为什么要使用依赖注入,它有什么好处。这时候需要提到解耦、易于测试、代码可维护性等优点。例如,通过依赖注入,可以轻松替换依赖的实现,方便单元测试。 最后,总结两者的应用场景实际开发中的使用方,确保用户有一个全面的理解。可能需要提醒一些最佳实践,比如优先使用构造函数注入,避免过度依赖自动装配导致的配置混乱。 检查是否有遗漏的点,比如常见的框架支持(Spring、Guice等),或者相关设计模式的关系。确保解释清晰,结构合理,用中文口语化表达,避免技术术语堆砌,让不同层次的用户都能理解。</think>### 依赖注入(Dependency Injection, DI) **定义**: 依赖注入是一种设计模式,核心思想是将对象之间的依赖关系从代码内部转移到外部容器管理。通过这种方,对象的创建绑定由外部控制,而非对象自身直接实例化依赖项。 #### 为什么需要依赖注入? 1. **解耦**:降低类与类之间的直接耦合,提高代码灵活性。 2. **可测试性**:便于替换依赖的模拟对象(Mock),简化单元测试。 3. **可维护性**:依赖关系集中管理,修改依赖实现时无需改动业务代码。 #### 实现方 1. **构造函数注入** 通过构造函数传递依赖对象。 ```java public class UserService { private final UserRepository userRepo; // 依赖通过构造函数注入 public UserService(UserRepository userRepo) { this.userRepo = userRepo; } } ``` 2. **Setter方法注入** 通过Setter方法设置依赖对象。 ```java public class UserService { private UserRepository userRepo; // 依赖通过Setter方法注入 public void setUserRepo(UserRepository userRepo) { this.userRepo = userRepo; } } ``` 3. **接口注入** 依赖对象通过接口方法注入(较少使用)。 --- ### 自动装配(Autowiring) **定义**: 自动装配是依赖注入的一种实现技术,由框架(如Spring)根据规则自动完成依赖对象的注入,无需手动配置。 #### 如何工作? - **规则匹配**:框架通过类型(`byType`)、名称(`byName`)或注解(如`@Autowired`)自动匹配依赖关系。 - **示例(Spring框架)**: ```java @Service public class UserService { @Autowired // 自动注入UserRepository的实现类 private UserRepository userRepo; } ``` #### 自动装配模式 1. **byType**:根据类型匹配依赖(需确保容器中只有一个该类型的Bean)。 2. **byName**:根据变量名与Bean名称匹配。 3. **@Qualifier**:配合`@Autowired`指定具体Bean的名称。 --- ### 依赖注入 vs. 自动装配 | **特性** | **依赖注入** | **自动装配** | |----------------|---------------------------|--------------------------------| | **范围** | 设计模式(理论概念) | 具体实现技术(依赖注入的自动化方) | | **配置方** | 手动或自动 | 完全由框架自动完成 | | **灵活性** | 高(可精细控制依赖) | 中(依赖框架的匹配规则) | --- ### 实际应用场景 1. **Spring框架**:通过`@Autowired`或XML配置实现自动装配。 2. **单元测试**:用Mock工具(如Mockito)注入模拟依赖。 3. **微服务架构**:管理服务之间的依赖关系。 --- ### 总结 - **依赖注入**是解耦提升代码质量的核心模式。 - **自动装配**是依赖注入的实践工具,依赖框架简化配置。 - 两者结合可显著提升开发效率,但需注意避免过度依赖自动装配导致的耦合问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值