目录
[2.2 Bean Name默认命名规则](#2.2 Bean Name默认命名规则)
[2.3 扫描路径](#2.3 扫描路径)
[2.5 @Autowired查找Bean顺序](#2.5 @Autowired查找Bean顺序)
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
@Componentpublic class UserController { } // 这是控制器吗?服务吗?看不出来
@Component
public class UserService { } // 这是服务层吗?工具类吗?无法分辨
@Component
public class UserDao { } // 这是数据访问层吗?不清楚
// 好的实践:语义明确
@Controllerpublic 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顺序
-
按类型查找 Bean
- 根据依赖的类型(Class/Interface)在 Spring 容器中查找匹配的 Bean。
-
判断是否找到
-
如果未找到 →报错
-
如果找到 → 进入下一步判断。
-
-
是否配置了
@Qualifier参数?-
如果已配置
@Qualifier → 按@Qualifier指定的名称进一步筛选 Bean。-
如果找到唯一匹配 → 装配成功 ✅。
-
如果未找到或仍匹配多个 → 抛异常 ❌。
-
-
如果**未配置
@Qualifier** → 进入默认策略(按字段名匹配)。
-
-
字段名匹配
-
匹配成功→装配成功
-
未匹配→说明未指定名称,进入下一判断
-
-
是否只有一个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 voidsetUserService (UserService userService) {
this.userService = userService;
}
}
Spring三种依赖注入方式优缺点对比
| 对比维度 | 构造方法注入 | Setter注入 | 属性注入 |
|---|---|---|---|
| 代码简洁性 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 可读性 | ✅ 优秀(依赖一目了然) | ✅ 良好 | 差(依赖关系隐藏) |
| 不可变性 | ✅ 支持final(线程安全) | 不支持final | 不支持final |
| 单元测试 | ✅ 最容易(直接传参) | ✅ 容易 | 困难(需要反射) |
| 依赖完整性 | ✅ 保证(对象创建即完整) | 不保证(可能部分注入) | 不保证 |
| 循环依赖检测 | ✅ 启动时报错 | ✅ Spring可处理 | ✅ Spring可处理 |
| 可选依赖支持 | ⭐ 有限(需Optional包装) | ✅ 优秀(required=false) | ✅ 支持 |
| 框架耦合度 | ⭐ 低 | ⭐ 低 | ✅ 高(强依赖Spring) |
| 代码重构 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ✅ 最容易 |