Spring DIIoC

news/2025/2/25 22:42:56

一.IoC

1.简介

什么是IoC?IoC,全称 Inversion of Control,控制反转。IoC是Spring的核心思想,Spring是⼀个“控制反转”的容器。

如果我们需要一个对象,正常来说我们是通过new一个对象,这个时候我们依赖的是new的这个对象。在Spring中,我们可以将一个类放入Spring,让Spring帮我们new这个类,我们自己就不用管 了,要用的时候只需要依赖注入(DI)即可。通过这个,我们也实现了对代码的解耦。

Spring提供了两类注解可以实现将对象放入容器管理这个目的:

1)类注解:@Controller@Service@Repository@Component@Configuration

2)方法注解:@Bean

2.获取Bean对象

我们能将对象放入容器中,也能将容器取出来。我们先获取Spring上下文对象,再使用上下文对象来获取到Bean对象。

Spring上下文(Spring context),是 Spring 框架的核心概念之一,它是一个容器,负责管理应用程序中的 Bean 对象及其生命周期,同时还提供了许多其他的功能(源代码中有详细介绍)。

getBean这个方法提供了五种方式:

第一种是使用 类的类型,第二种使用 Bean名 和 类的类型,第三种使用 类的类型 和 构造函数参数,第四种使用 Bean名,第五种使用 类名 和 构造函数参数。

这里举几个例子:

java">ApplicationContext context=SpringApplication.run(Springdemo03Application.class, args);
//Hello是个类
Hello hello1=context.getBean(Hello.class);
Hello hello2= (Hello) context.getBean("hello");

这里要注重强调一个点,就是这个Bean名。这个Bean名不是类的名称,而是有其独特的命名。

Bean名的命名规则如下:对于一般类名,Bean以小写字母开头,然后使用驼峰式大小写;如果类名有多个字母,并且第一个和第二个字母为大写,那么Bean名与类名相同。

例如:UserController --> userController     UController --> UController。

我们通过这个方法获取的相同名称或类型的Bean,这些Bean对象都是同一个。

3.类注解

将这些注解加到类上,表示这个类被放入容器中啦。

1)@Controller(控制器存储)

@Controller:控制层,接收请求,对请求进行处理,并进行响应

java">@Controller
public class UserController {
    public String name;
}

2) @Service(服务存储)

@Servie:业务逻辑层,处理具体的业务逻辑

java">@Service
public class UseServicer {
    public String name;
    public void print(){
        System.out.println(name);
    }
}

3) @Repository(仓库存储)

@Repository:数据访问层,也称为持久层。负责数据访问操作

java">@Repository
public class UserRepository {
    public String name;
    public void print(){
        System.out.println(name);
    }
}

4)@Component(组件存储)

java">@Component
public class UserComponent {
    public String name;
    public void print(){
        System.out.println(name);
    }
}

5)@Configuration(配置存储)

@Configuration:配置层,处理项目中的⼀些配置信息

java">@Configuration
public class UserConfiguration {
    public String name;
    public void print(){
        System.out.println(name);
    }
}

 6)总结

打开上述注解的源码,我们会发现它们中都有 @Component 这个注解。上述注解其实是 @Component 这个注解的衍生注解,而我们对这些注解进行拆解的原因是方便更好的分层。

4.方法注解

方法注解,顾名思义,就是加在方法上的注解。使用方法注解主要是为了解决这两个问题,一是使用外部包的类没办法添加类注解,二是一个类可能需要多个对象。

这里要注意,使用@Bean,这个方法所属的类必须加上类注解。

java">@Service
public class Hello {
    @Bean
    public User user(){
        User user=new User();
        user.name="111";
        return user;
    }
}

那如何实现同一个类注入多个对象呢?很简单,写两个不就行了。但是,当我们运行的时候就会发现报错了:required a single bean, but 2 were found.

这个报错告诉我们:这个容器里面有两个对象,它也不知道该用哪个。

方法一:我们在通过Spring上下文获取Bean的时候使用Bean名来获取;

方法二:重命名,对Bean进行重命名,这个名可以写一个,也可以写多个

java">//@Bean("u1")
@Bean(name = {"u1","u3"})
public User user1(){
    User user=new User();
    user.name="111";
    return user;
}

二.DI

1.简介

什么是DI?DI,全称 Dependency Injection,依赖注入。什么是依赖注入?容器在运行期间,动态的为应用程序提供运行时所依赖的资源。可以理解成我们可以从容器中取出放入容器中的类。

2.注入方法

1)属性注入(Field Injection)

我们通过 @Autowired 这个注解来实现属性注入,实现起来相当简单,一行就解决了。

优点:简洁,使用方便。

缺点:只能用于IoC容器;不能输入Final修饰的属性。

java">@Controller
public class HelloController {
    @Autowired
    public User user;
    public void print(){
        user.print();
    }
}

2)构造方法注入(Constructor Injection)

将 @Autowired 这注解加在构造方法上,构造方法上的这个user就是从容器中取的。

优点:可以注入final修饰的属性;注入的对象不会被修改;依赖对象在使用前一定会被完全初始化;通用性好。

缺点:注入多个对象,处理起来比较麻烦。

java">@Controller
public class HelloController {
    public User user;
    @Autowired
    public HelloController(User user){
        this.user=user;
    }
    public void print(){
        user.print();
    }
}

3)Setter注入(Setter Injection)

将 @Autowired 这个注解加在setter方法上,setter方法上的user就是从容器中取的。

优点:方便在类实例化后重新对该对象进行配置或者注入。

缺点:不能注入final修饰的属性;注入对象可能被改变。

java">@Controller
public class HelloController {
    public User user;
    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
    public void print(){
        user.print();
    }
}

3.Bean不唯一

上面的代码都是建立在同一个类只有一个对象放入了容器中,那如果同一个类有多个对象呢?

1)@Primary

@Primary 可以确认一个默认的实现,也就是说可以指定一个类,我就取这个类,就是这个意思。

java">@Service
public class Hello {
    public void print(){
        System.out.println("hello world");
    }
    @Bean
    @Primary
    public User user1(){
        User user=new User();
        user.name="111";
        return user;
    }
    @Bean
    public User user2(){
        User user=new User();
        user.name="222";
        return user;
    }
}

2)@Qualifier

@Qualifier 可以指定当前要注入的对象,这个注解的用法跟上面的 @Primary 其实正好相反(代码可以看出)。@Qualifier 是加在要注入的对象上的,@Qualifier 必须要与 @Autowired 一起使用。

java">@Controller
public class HelloController {
    @Autowired
    @Qualifier("user1")
    public User user;
    public void print(){
        user.print();
    }
}

3)@Resource

@Resource 是按照Bean的名称进行注入的

java">@Controller
public class HelloController {
    @Autowired
    @Resource(name="user1")
    public User user;
    public void print(){
        user.print();
    }
}

4)@Autowired 的装配顺序


http://www.niftyadmin.cn/n/5865996.html

相关文章

记录一下_treafik使用Gateway-APi使用的细节参数

一、这里说一下treafik最大的容易走入圈套的地方。 1、treafik默认不是hostnetwork模式。为了暴露自己出来它有一个LB类型的SVC。 这里的External_ip为我的节点IP,因为使用了k3s自带的LB,这个SVC就很容易绕进去。 1、第一个这个LB的作用是为了暴露treafi…

基于C#+SQL Server设计与实现的教学管理信息系统

教学管理信息系统 1、实验内容: 大学同时开设多门课程。每门课程有一个主讲教师,有多名学生选修;一个学生可选修多门课程并获得相应的学分和成绩;上课的基本单位是“次”(一次 2 学时),每一次…

若依前后端分离框架修改3.8.9版本(重点在安全框架讲解与微信小程序登录集成)

若依模板改造(3.8.9) 1、基础改造 下载代码 从[RuoYi-Vue: 🎉 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本](https://gitee.co…

Flutter 实现抖音风格底部导航栏

在移动应用开发中,良好的导航设计对用户体验至关重要。抖音作为一款现象级应用,其底部导航设计简洁直观,极具吸引力。本文将详细介绍如何使用 Flutter 开发一个类似抖音风格的底部导航栏,帮助开发者打造兼具美观与实用的导航界面。…

找不到依赖项 <…> (Maven)

IDEA 的 build 操作和 maven 的 build 操作是分开的 重新加载 Maven 项目

RabbitMQ教程超详细(零基础入门有空更新)

1:入门第一步就是闲着没事看看RabbitMQ官网,更新什么。 这是官网地址 RabbtiMQ官网 2:这是基于erlang开发的,所以需要erlang环境。 优先下载环境 Releases rabbitmq/erlang-rpm GitHub 3:下载RabbitMQ安装包 RabbtiMQ安装包 4:上传自己的服务器上面 懂得人已经…

Linux红帽:RHCSA认证知识讲解(二)配置网络与登录本地远程Linux主机

Linux红帽:RHCSA认证知识讲解(二)配置网络与登录本地远程Linux主机 前言一、使用命令行(nmcli 命令)配置网络,配置主机名第一步第二步修改主机名称 二、使用图形化界面(nmtui 命令)配…

2025年AI科技热点全景:人形机器人量产、垂类应用崛起与推理模型革新引领未来

一、人形机器人量产:从实验室到工业场景的跨越 1. 技术突破与产业链重构 2025年被广泛视为人形机器人量产元年,其核心驱动力源于“大脑、小脑、肢体”三位一体的技术突破。 大脑层:基于Transformer的多模态大模型(如NVIDIA Cosmos平台)实现了环境感知与决策优化,例如优…