Spring IoC&DI

目录

1.Spring是什么?

2.详解Ioc

2.1Bean的存储

2.2 Bean Name默认命名规则

2.3 扫描路径

2.4@Autowired和@Resource区别

2.5 @Autowired查找Bean顺序

3.详解DI

Spring三种依赖注入方式优缺点对比


1.Spring是什么?

Spring 是一个开源的 Java 开发框架,核心目标是简化企业级应用开发。它提供了模块化工具(如 Spring MVC、Spring Security、Spring Data 等),让开发者更专注于业务逻辑,而非重复的底层代码。也就是包含了众多方法的IoC容器,

容器是什么?

在 Spring 中,容器是一个 装对象的“盒子”,它负责创建、配置、组装你编写的 Java 对象(称为 Bean),并管理它们的生命周期。

Ioc(控制反转)是什么?

谁使用谁控制=>Spring来控制

是 Spring 的核心思想。传统代码中,对象自己控制依赖的创建(如 new Service());而 IoC 将控制权“反转”给容器——你只需声明依赖关系,容器自动注入所需对象。

例如:

// 传统方式:程序员自己创建依赖 UserService service = new UserService(); // IoC 方式:容器自动注入依赖 @Autowired private UserService service;

简述Ioc和di

控制反转(IoC)的核心思想是将对象的创建和管理权从传统的“谁使用谁控制”模式转变为由框架(如Spring)统一管理。这种方式有效降低了组件间的耦合度,使系统更易于维护和扩展。

在IoC模式下,对象的生命周期完全由Spring容器管理,开发者无需手动实例化对象。依赖注入(DI)是IoC的一种实现方式,通过DI,Spring容器在运行时自动将依赖的对象注入到目标组件中,开发者只需声明依赖关系即可获得所需实例。

通过在类上面注释@Component:告诉Spring将该对象的控制权转给Spring

在类中注明依赖之后注释@Autowired:表明从Spring容器中拿出该对象并赋值给注明的依赖

2.详解Ioc

2.1Bean的存储

Spring为了更好地完善web服务提供许多注解能够完成对象的存储,代替@Component

类注解:@Controller,@Service,@Repository,@Component,@Configuration

方法注解:@Bean

类注解:

@Controller(控制器存储)

@Controller public class UserController { public String sayHello(){ return "Hello World!"; } }public static void main(String[] args) { //应用上下文 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args); //通过getBean方法观察是否能拿到UserController对象 //拿到说明通过@Controller,对象成功创建并且存储到Spring容器当中 UserController bean = context.getBean(UserController.class); System.out.println(bean.sayHello()); }

其他注解均可用同样的方法验证存储功能,如@Service:

@Service public class UserService { public String doService(){ return "doService"; } }@SpringBootApplication public class SpringIocDemoApplication { public static void main(String[] args) { //应用上下文 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args); UserService bean = context.getBean(UserService.class); System.out.println(bean); } }

因此后续类注解同上验证不做过多重复解释,既然起到效果相似,为什么还要有这么多?

原因是为了语义更加清晰,提高可读性,在对应的三层架构中使用对应的注解能更好的理解语义

// 不好的实践:因为其余注解都是@Component的衍生注解,因此都使用@Component
@Component
public class UserController { }  // 这是控制器吗?服务吗?看不出来

@Component  
public class UserService { }     // 这是服务层吗?工具类吗?无法分辨

@Component
public class UserDao { }         // 这是数据访问层吗?不清楚

// 好的实践:语义明确
@Controller

public class UserController { }  // 明确是控制器,处理HTTP请求

@Service
public class UserService { }     // 明确是服务层,处理业务逻辑

@Repository
public class UserDao { }         // 明确是数据访问层

方法注解:开发人员自己创建对象交给Spring去管理,用于解决同一个类需要多个对象的问题/创建第三方对象

注意:需配合类注解使用

UserInfo类 @AllArgsConstructor//有参构造方法 @NoArgsConstructor//无参构造方法 @Data public class UserInfo { private String name; private int age; }
BeanConfig类 @Configuration public class BeanConfig { @Bean public UserInfo userInfo(){ return new UserInfo("zhangsan",12);//自主创建对象 } }
@SpringBootApplication public class SpringIocDemoApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args); UserInfo bean1 = context.getBean(UserInfo.class); System.out.println(bean1); } }

可以看到能够通过@Bean使Spring得到对UserInfo对象的控制权

接下来解决多个对象创建的问题

@Configuration public class BeanConfig { //创建两个UserInfo对象,方法名区分开@Bean public UserInfo userInfo(){ return new UserInfo("zhangsan",12); } @Bean public UserInfo userInfo2(){ return new UserInfo("lisi",16); } }@SpringBootApplication public class SpringIocDemoApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args); //只靠类型无法区分对象,因此传入对象名作为参数 UserInfo bean1 = context.getBean("userInfo",UserInfo.class); System.out.println(bean1); UserInfo bean2 = context.getBean("userInfo2",UserInfo.class); System.out.println(bean2); } }

2.2 Bean Name默认命名规则

(1)类注解

  • 类名前两位为大写,如USerinfo=>bean name 为原类名
  • 其他情况=>bean name 为类名的小驼峰形式

(2)方法注解

  • bean name 为方法名

2.3 扫描路径

默认情况下,Spring Boot只扫描启动类所在包及其子包

但是可以通过@ComponentScan(basePackages="")来指定要扫描的路径

2.4@Autowired和@Resource区别

@Autowired是Spring提供的注解,根据类型进行注入

@Resource是JDK提供的注解,根据名称注入

2.5 @Autowired查找Bean顺序

  1. 按类型查找 Bean
    • 根据依赖的类型(Class/Interface)在 Spring 容器中查找匹配的 Bean。
  2. 判断是否找到
    • 如果未找到​ →报错
    • 如果找到​ → 进入下一步判断。
  3. 是否配置了 @Qualifier参数?
    • 如果已配置 @Qualifier​ → 按 @Qualifier指定的名称进一步筛选 Bean。
      • 如果找到唯一匹配 → 装配成功 ✅。
      • 如果未找到或仍匹配多个 → 抛异常 ❌。
    • 如果未配置 @Qualifier​ → 进入默认策略(按字段名匹配)。
  4. 字段名匹配
    • 匹配成功→装配成功
    • 未匹配→说明未指定名称,进入下一判断
  5. 是否只有一个Bean
    • 如果只有一个bean → 直接装配

3.详解DI

依赖注入是一个过程,是ioc容器创建Bean的过程中提供所依赖的资源,这个资源就是对象

Spring提供了三种方式:

(1)属性注入@Autowired

@Component
public class UserService {
    
    // 方式1:直接注入到属性
    @Autowired
    private UserRepository userRepository;
}

(2)构造方法注入

@Service
public class UserService {
    
    // 使用final,确保依赖不可变
    private final UserRepository userRepository;
    
    // 构造方法注入
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
 

注意:

  • 只有一个构造方法时默认执行这一个
  • 多个构造方法默认执行无参构造,若没有无参构造则报错
  • 可通过@Autowired注解指定执行的构造方法

(3)Setter注入


@Service
public class UserService {
    
    private UserService userService;
    
    // Setter注入
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
   
}

Spring三种依赖注入方式优缺点对比

对比维度

构造方法注入

Setter注入

属性注入

代码简洁性

⭐⭐⭐

⭐⭐⭐⭐

⭐⭐⭐⭐⭐

可读性

优秀(依赖一目了然)

良好

 (依赖关系隐藏)

不可变性

支持final(线程安全)

不支持final

 不支持final

单元测试

最容易(直接传参)

容易

 困难(需要反射)

依赖完整性

保证(对象创建即完整)

 不保证(可能部分注入)

 不保证

循环依赖检测

启动时报错

Spring可处理

Spring可处理

可选依赖支持

⭐ 有限(需Optional包装)

优秀(required=false)

支持

框架耦合度

⭐ 低

⭐ 低

(强依赖Spring)

代码重构

⭐⭐⭐

⭐⭐⭐⭐

最容易

Read more

【002】Windows系统下Java下载 JDK

文章目录 * @[TOC](文章目录) * 前言 * **1. 下载 JDK** * **2. 安装 JDK** * **3. 配置 JAVA_HOME 环境变量** * **4. 验证安装是否成功** * **常见问题与提示** 前言 这里下载安装的是 java17 的jdk 1. 下载 JDK * Oracle 官方 JDK 17: * 官网地址:https://www.oracle.com/java/technologies/downloads/#jdk17 * 注意:需要注册/登录 Oracle 账户。 * 或者选择 OpenJDK 17(推荐,无需登录): * 推荐发行版:Eclipse

By Ne0inhk
【LeetCode必刷好题】:Java顺序表实现杨辉三角

【LeetCode必刷好题】:Java顺序表实现杨辉三角

🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:Java.数据结构 【前言】 杨辉三角作为经典的数学与编程结合案例,是理解二维数组和动态列表操作的绝佳素材。本文将带你从逻辑拆解、问题分析、优化方向等角度进行详细解析,带你彻底掌握杨辉三角的实现精髓。 文章目录: * 一、杨辉三角思路分析 * 二、代码实现 * 三、总结 一、杨辉三角思路分析 杨辉三角每一行数字都是上一行两个相邻数字之和 思路分析: 创建一个二维列表List<List<Integer>>,储存整个三角外层循环控制行数 i,0~numRows内层循环是列数 j,小于 i每一行第一个和最后一个是1中间元素通过上一行相邻元素加得 二、代码实现 publicclassTest{publicList<List<Integer&

By Ne0inhk
计算机毕业设计java基于javaweb的超市销售管理系统 基于B/S架构的超市进销存与销售管理平台设计与实现 面向零售业的商品采购与销售订单管理系统开发

计算机毕业设计java基于javaweb的超市销售管理系统 基于B/S架构的超市进销存与销售管理平台设计与实现 面向零售业的商品采购与销售订单管理系统开发

计算机毕业设计java基于javaweb的超市销售管理系统2kf7s9 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 随着零售行业的快速发展和市场竞争的日益激烈,超市作为商品流通的重要终端,其管理效率直接影响着经营成本和盈利能力。传统的超市销售管理多依赖于手工记账、纸质单据或单机Excel表格,存在商品信息更新不及时、库存管理混乱、销售数据难以统计、会员信息分散等问题,难以满足现代化超市对高效、精准、智能化管理的需求。基于JavaWeb的超市销售管理系统应运而生,它通过互联网技术将员工信息、会员档案、供应商管理、商品分类、商品信息、商品采购、销售订单等功能进行数字化整合,实现了超市销售全流程的线上化、规范化管理。该系统不仅提升了超市运营效率,也为管理者提供了数据驱动的决策支持,成为零售业数字化转型的重要工具。 系统核心功能概览: * 用户注册与登录:支持员工、管理员两类角色的注册与登录。 * 个人中心:用户可查看和修改个人资料,如员工工号、姓名、性别、手机、头像等。 * 员工管理:管理员可管理员工信

By Ne0inhk
JDK的下载与安装:从入门到精通

JDK的下载与安装:从入门到精通

一、什么是JDK? JDK(Java Development Kit)是Java开发工具包的缩写,它是Java开发的核心组件。JDK不仅包含了Java运行环境(JRE),还包含了一系列开发工具(如编译器javac、调试器jdb等)和基础类库。 JDK组成结构 JDKJRE开发工具JVM核心类库javacjavajavadocjdb 二、JDK下载指南 1. 选择JDK版本 目前主流版本有: * Java 8(LTS长期支持版) * Java 11(LTS) * Java 17(LTS) * 最新版本(如Java 21) 对于初学者,建议选择Java 11或Java 17,因为它们都是长期支持版本。 2. 下载步骤 1. 访问Oracle官网:https://www.oracle.com/java/technologies/ 2. 选择&

By Ne0inhk