Spring入门(二)快速入门 - IOC/DI

本文详细介绍了Spring的核心概念IOC(控制反转)和DI(依赖注入),通过代码实例展示了如何使用@Configuration和@Bean进行配置,以及如何通过@Autowired进行组件自动匹配和注入。文章还讨论了接口解耦和依赖注入的规则,强调了面向接口编程的重要性。

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

前言
一、Spring核心之 IOC 、DI
1. IOC
IOC(Inversion of Control):控制反转
控制反转指的是将对象的创建、管理权限从我们程序猿的手里,移交给我们Spring框架。
这时我们不再有创建、管理对象的主动权,改为被动的接收、使用,这种控制权的转换我们称之为控制反转。

主动控制:适合创建简单对象。
控制反转:适合管理创建过程复杂的对象。

2. DI
DI(Dependency Injection):依赖注入
依赖注入指的是在程序运行期间,由外部容器(Spring)动态的将依赖对象注入到组件中。其实IOC 和 DI 其实是同一个概念。依赖注入是实现控制反转的方式。
目的:解耦
关系:has a

从概念来讲,实际太过于抽象,作为刚刚接触Spring框架的小伙伴们来说,真心不能够理解,实际我也曾经是其中的一员。但是对于操作来讲极其简便。这就是我上文说到的,刚刚学习框架,要做到不求甚解。

举个例子:
我们要完成某样有实际意义的功能,一般来讲都需要两个或两个以上的类组成,并互相之间协作完成的结果。按照传统来讲,我们的每个对象都需要管理和自己互相协作的对象(它所以依赖的对象)的引用,这将导致高度耦合。
而如果我们通过DI,这种对象的依赖关系就由Spring这个框架去进行管理,那我们就实现了松耦合。其次我们现在都是基于接口编程,也是使得其解耦低的原因所在,实现了可替换性。

在这里插入图片描述
面向接口编程(解耦 / 松耦合)

 在这里插入图片描述

 
二、第一个Spring项目
1. IOC - 代码实现
1.1 第一种方式:@Configuration + @Bean
项目结构:

在这里插入图片描述


创建一个 Maven 项目,

导入依赖 (pom.xml)

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
</dependencies>
pom.xml 文件 如图所示:

在这里插入图片描述
创建JavaBean - DemoBean

/**
 * @Author lss
 */
public class DemoBean {
}

创建配置类

/**
 * @Author lss
 */
@Configuration
public class Config {

    @Bean
    public DemoBean getDemoBean() {
        return new DemoBean();
    }

}

测试 DemoBean 对象是否交给Spring去管理

/**
 * @Author lss
 */
public class IOCTest {
    public static void main(String[] args) {
        // 初始化Spring容器
        ApplicationContext ac =
                new AnnotationConfigApplicationContext(Config.class);
        // 获取被管理的JavaBean
        DemoBean bean = ac.getBean(DemoBean.class);
        System.out.println(bean);
    }
}
当然这里如果已经对于Juint 单元测试 有些了解的情况下,我们测试也可以使用 Juint,能达到同样的效果

在 pom.xml 文件中 导入 Juint 单元测试依赖

<!-- 单元测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>
pom.xml 文件 如图所示:

在这里插入图片描述

@Test
public void testIOC() {
    // 初始化Spring容器
    ApplicationContext ac =
            new AnnotationConfigApplicationContext(Config.class);
    // 获取被管理的JavaBean
    DemoBean bean = ac.getBean(DemoBean.class);
    System.out.println(bean);
}
如图所示:

 在这里插入图片描述

运行输出结果为:

在这里插入图片描述
1.2 第二种方式:@Component + @ComponentScan 组件扫描
创建JavaBean - ExampleBean,类上添加 @Component 注解

/**
 * @Author lss
 */
@Component
public class ExampleBean {
}

在配置类上,添加 @ComponentScan 注解

/**
 * @Author tedu-sysh-lrf
 */
@Configuration
@ComponentScan("cn.cy.bean")
public class Config {

    @Bean
    public DemoBean getDemoBean() {
        return new DemoBean();
    }

}

测试在这里插入图片描述

运行输出结果为:

在这里插入图片描述
2. DI - 代码实现
DI(依赖注入) 在上面讲述概念的时候已经提到过了,咱们这里再简单的剖析下:
依赖注入实际来讲分为两部分:

依赖(dependency)
实际依赖我们之前学习 maven 项目的时候就已经接触过这个名词 ,添加依赖 / 导入依赖…
那么什么才是我们的依赖呢?
依赖通俗意义上来讲,是指一个业务功能执行期间所需要的前提:煮米饭必须以米为前提,砍树需要以工具为前提。

<dependencies>
    <!-- spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
        <scope>test</scope>
    </dependency>
</dependencies>

注入
注入是指将我们需要的依赖给到 / 传递到使用者,我们称为注入。
实际我们在获取这个依赖的时候可以通过两种方式:主动获取(对象自己创建),和被动得到(对象别人创建,给只管使用即可)。而我们被动得到我们称之为注入。
以煮饭为例:米的生产过程我不需要关注,我只需要去使用即可,这个就是我们被动得到。
以砍树为例:工具的生产过程我不需要关注,我只需要去使用即可,这个就是我们被动得到。

我们这里还是以刚才的项目进行使用测试。

在这里插入图片描述
创建一个 Maven 项目,

导入依赖 (pom.xml)

<dependencies>
   <!-- spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
        <scope>test</scope>
    </dependency>
</dependencies>

创建JavaBean - Saw / Worker
Saw

/**
 * @Author lss
 */
public class Saw implements Serializable {

    private String name = "电锯";

    @Override
    public String toString() {
        return name;
    }
}
Worker

/**
 * @Author lss
 */
public class Worker implements Serializable {

    private String name = "光头强";

    public Saw saw;

    public void work() {
        System.out.println(name +"使用" + saw + "砍树");
    }
}
创建配置类

/**
 * @Author lss
 */
@Configuration
public class Config {

    @Bean
    public Saw saw() {
        return new Saw();
    }

    @Bean
    public Worker worker(Saw s) {
        Worker worker = new Worker();
        worker.saw = s;
        return worker;
    }    }
创建测试类,测试,Saw对象是否被注入到 Worker对象中

/**
 * @Author tlss
 */
public class DITests {

    @Test
    public void testDI() {
        ApplicationContext ac =
                new AnnotationConfigApplicationContext(Config.class);
        Worker bean = ac.getBean("worker",Worker.class);
        bean.work();
    }

}
运行输出结果为:

在这里插入图片描述

2.1 Spring IOC组件注入时组件自动匹配规则


首先按照注入参数类型查找响应类型的Bean组件,如果没有则直接报错
如果在Spring容器中能够匹配上唯一类型的Bean组件,则进行注入成功
如果按照类型匹配到两个或两个以上的bean组件,则在查找组件ID和变量名是否匹配,如果匹配则注入成功
如果组件类型和组件ID都不能很好的匹配则报错


2.2 @Autowired


注解方式进行注入:
修改上述代码:
通过@Component将 Saw 和 Worker 对象交给Spring去管理

在这里插入图片描述

通过 @Autowired 注解,将 Saw 对象注入进去

在这里插入图片描述

在配置类上添加 @ComponentScan 注解,扫描组件

在这里插入图片描述

同样进行测试,得到相同的结果

在这里插入图片描述

一般来讲,我们开发中这种方式使用更加简便,也是我们常常使用的方式。

2.3 接口解耦


面向接口编程(解耦 / 松耦合)在这里插入图片描述

我们在上述代码上进行修改即可
添加 工具接口 Tool在这里插入图片描述

添加 具体的工具-斧子 Ax ,实现工具接口Tool,并添加@Component注解在这里插入图片描述

修改 具体的工具-锯 Saw ,实现工具接口Tool

在这里插入图片描述
修改 Worker类 ,修改注入对象,将注入对象类型改为接口类型

在这里插入图片描述

运行测试类:
这时我们的程序会报错,这个是正常的现象,或者说是我们想要出现的效果,这里我们来看下报错信息,分析下报错原因

在这里插入图片描述
这里出现了一个异常:NoUniqueBeanDefinitionException 不唯一的bean定义异常
异常错误描述:

没有一个合适的bean类型(cn.cy.bean.Tool)可用,预期有一个单独的匹配的bean,但是找到了 2个 (saw,ax)
这里可以理解为,当我们想把工具注入到Worker对象中时,Spring容器找到了两个Tool工具类型,不知道应该注入哪个类型了,所以会抛出一个 NoUniqueBeanDefinitionException 异常。

解决办法:

这时,我们只需要去指定一下我们我们想要注入的类型即可

那这里需要先了解下@Autowired的注入规则

2.3 @Autowired的注入规则


首先按照类型进行注入(byType),如果没有则直接报错
如果在 Spring容器 中能够匹配到唯一类型的 Bean 组件,则注入成功
如果按照类型匹配到两个或两个以上的组件,则再查找组件ID和变量名是否匹配(byType),如果匹配则注入成功
如果组件类型和组件ID都不能很好的匹配则报错


根据上面的注入规则,有以下两种解决办法:

利用组件自定义ID,当组件ID设置为 tool 时, @Autowired 注解会根据ID匹配成功
利用注解 @Qualifier(“beanID”)指定注入bean组件的ID
第一种解决办法:
将具体想要注入的组件,自己定义ID(名字),这样和要注入的名字一致,这样就可以注入进去了,但是这种方式不太常见,我们一般都是保证原生默认的beanID

在这里插入图片描述
第二种解决办法:
直接在要注入的地方添加 @Qualifier 注解,告诉 Spring容器通过 指定的beanID(名字)进行注入

在这里插入图片描述


如想了解其他异常,可见常见异常汇总:

 常见异常汇总链接:xxx(更新中…)


3. 专有名词


3.1 Java Bean


Bean 的英文意思是 “豆子”

JavaBean 是一种约定 Java 类的定义规范,使得我们程序规范一致,方便使用,交流。它是企业通用的一种编程标准,建议大家都去遵守。
约定:

需要定义包 package
有无参的构造方法(无参构造器)
需要实现序列化接口
类中声明 getXxx 和 setXxx 方法(getter ,setter 方法)


Spring 同样建议被其管理的对象符合 JavaBean 规范。并且我们通常意义上称呼的 JavaBean对象 就是由 Spring 容器管理的对象,我们也称 Spring 为 Spring容器,IOC容器…

4. 注解


如想了解其他注解 / 注解的具体用法,可见常见异常汇总:

 常见注解汇总链接:xxx(更新中…)


4.1 @Bean


告诉 Spring 在启动时,加载被 @Bean 标注的方法,返回值就是 Spring 创建的对象(交给 Spring 管理的对象)方法名是 Bean 的ID

4.2 @Configuration


由 @Configuration 标注的类,告诉 Spring 它是一个配置类

4.3 @Component


通用组件注解
下面的组件注解是 @Component 注解的衍生注解,主要目的是为了提高标记代码的 “可读性”

4.3.1 @Controller


控制层组件注解

4.3.2 @Service


业务层组件注解

3.3.3 @Repository
持久层组件注解

4.4 @ComponentScan
@ComponentScan 作用是根据定义的扫描路径,把符合扫描规则的类装配到 Spring 容器中

4.5 @Autowired
自动注入注解

4.6 @Qualifier
与 @Autowired 配合使用,当存在多个实例的时候,指定具体实例的名称

4.7 @Test
junit 单元测试注解

总结
文章知识点与官方知识档案匹配,可进一步学习相关知识
 

1、安装maven 2、eclipse安装m2eclipse插件 打开Eclipse菜单栏Help->Eclipse Marketplace 输入“Maven”搜索到插件Maven Integration for Eclipse 并点击insall安装 3、安装成成之后我们在Eclipse菜单栏中点击File->New->Other 在弹出的对话框中点击Maven文件夹 点击Maven Project,并点击Next,到下一个对话框是默认设置,继续点击Next到下面这一步 选择maven-archetype-quickstart,点击Next 4、配置pom.xml , 加上以下依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> propertities标签里面加上version信息: <springframework.version>3.2.0.RELEASE</springframework.version> 保存pom.xml后等待下载组件。 5、写代码 如果发现出现applicationContext could not resolve to a type, 可能是依赖没下载完或者下载失败,或者jar包出现问题,解决方法删除这个jar包,然后重新下载。在Eclipse中选中项目右键展开run as,然后选中maven install,重新下载jar包。 https://blog.youkuaiyun.com/linxc008/article/details/81054526 applicationContext.xml要加在src/java/resources下 6.bulid project 右击项目,点击Run as, 选择Maven build... , 在弹出的窗口中的Goals栏填上Maven命令:clean package,然后点击Run.然后在有main函数的java文件上右键点击Run As Java Application 注: applicationContext.xml 配置bean信息所依赖的class路径要一致且大小写敏感,否则运行时会出现java.lang.NoClassDefFoundError (wrong name)。 https://blog.youkuaiyun.com/my_bkn/article/details/6875481
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值