🔥个人主页: 中草药
🔥专栏:【Java】登神长阶 史诗般的Java成神之路
在 Java 开发的世界里,Spring 框架无疑是一颗璀璨的巨星,而其中的**控制反转(Inversion of Control,简称 Ioc)**和**依赖注入(Dependency Injection,简称 DI)**更是其核心特性之一。今天,就让我们一起深入探索 Spring 中的 Ioc 和 DI。
🥼一、IoC (Inversion of Control)
1、概念
Ioc,即控制反转(Inversion of Control),是一种重要的设计思想。
在传统的编程模式中,对象的创建和依赖关系的管理通常由程序员在代码中显式地进行。例如,一个对象 A 如果依赖于对象 B,那么在对象 A 的代码中就需要主动去创建对象 B。而在 Spring 的 Ioc 容器中,对象的创建和依赖关系的管理被反转了过来,不再由对象自身来管理,而是由容器来负责。
举例:
2、理解
需求:造一辆车
我们的实现思路:
先设计轮子(Tire),然后根据轮子的大小设计出底盘(Bottom),接着根据底盘设计出车身(Framework),最后根据车身设计好整个的汽车(Car),这里存在一个依赖关系
代码如下:
public class Car {
private Framework framework;
public Car(int size) {
this.framework = new Framework(size);
System.out.println("car init...");
}
public void run() {
System.out.println("car run...");
}
}
public class Framework {
private Bottom bottom;
public Framework(int size) {
this.bottom = new Bottom(size);
System.out.println("framework init...");
}
}
public class Bottom {
private Tire tire;
public Bottom(int size) {
this.tire = new Tire(size);
System.out.println("bottom init...");
}
}
public class Tire {
private int size;
public Tire(int size) {
System.out.println("tire size:" + size);
}
}
当我们用IoC的思想去修改以上代码
如图,改进之后的控制权发生了翻转,不再是使用方创建并控制对象,而是把依赖对象注入到当前的对象,依赖对象的控制权不再由当前类控制
public class Car {
private Framework framework;
public Car(Framework framework) {
this.framework = framework;
System.out.println("Car init....");
}
public void run() {
System.out.println("Car run...");
}
}
class Framework {
private Bottom bottom;
public Framework(Bottom bottom) {
this.bottom = bottom;
System.out.println("Framework init...");
}
}
class Bottom {
private Tire tire;
public Bottom(Tire tire) {
this.tire = tire;
System.out.println("Bottom init...");
}
}
class Tire {
private int size;
public Tire(int size) {
this.size = size;
System.out.println("轮胎尺寸:" + size);
}
}
3、优点
- 资源集中管理:LoC实现了资源的集中管理,实现资源的可配置和易管理
- 松耦合:降低使用资源双方的依赖程度
Spring就是一种IoC容器,帮助我们来进行资源管理
🦺二、DI(Dependency Injection)
1、概念
在软件开发中,当一个类(称为依赖类)需要使用另一个类(称为被依赖类)的功能时,传统的做法是在依赖类中直接创建被依赖类的实例。但这样会导致依赖类和被依赖类之间的耦合度较高,不利于代码的维护和扩展。
而依赖注入则是将被依赖类的实例通过外部方式(如构造函数、Setter 方法、字段注入等)注入到依赖类中,从而实现依赖类和被依赖类之间的解耦。
IoC是一种思想,DI相当于他的具体实现
** 2、实现方式**
1.**属性注入**,主要通过@Autowired实现的,例如:
@Controller
public class UserController {
//注⼊⽅法1: 属性注⼊
@Autowired
private UserService userService;
public void sayHi(){
System.out.println("hi,UserController...");
userService.sayHi();
}
}
2**.构造方法注入**:在依赖类中提供 Setter 方法,用于接收被依赖类的实例。例如
@Controller
public class UserController2 {
//注⼊⽅法2: 构造⽅法
private UserService userService;
@Autowired
public UserController2(UserService userService) {
this.userService = userService;
}
public void sayHi(){
System.out.println("hi,UserController2...");
userService.sayHi();
}
}
3.**Setter方法注入**:使用注解等方式直接在依赖类的字段上注入被依赖类的实例。例如(在 Spring 框架中):
@Controller
public class UserController3 {
//注⼊⽅法3: Setter⽅法注⼊
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(){
System.out.println("hi,UserController3...");
userService.sayHi();
}
}
3、优缺点对比
~属性注入
** 优点:**只能针对IoC容器,并且只有在使用时抛出NPE
** 缺点:**不能注入一个Final修饰的属性
~构造函数注入(Spring 4.x推荐)
** 优点:**
** 1. **可以注入Final修饰的属性
2.注入的对象不会被修改
3.依赖对象在使用之前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而
构造方法是在类加载阶段会执行的
4.通用性好,构造方法是JDK支持的,所以他适用于任何框架
** 缺点:**注入多个对象,代码会比较繁琐
~Setter注入 (Spring 3.x推荐)
** 优点:**方便在类实例之后,重新对该对象进行配置或者注入
** 缺点:**不能注入Final修饰的属性,注入对象可能会被改变
4、@Autowired存在问题
如下代码,当同一类型出现多个Bean对象时,会报错:
@Component
public class BeanConfig {
@Bean("u1")
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
@Controller
public class UserController {
@Autowired
private UserService userService;
//注入user
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
userService.sayHi();
System.out.println(user);
}
}
运行结果:
报错原因:非唯一的Bean对象
Spring提供了以下三种解决方案
1.@Primary
- 作用:当存在多个相同类型的 bean 可供注入时,使用
@Primary
注解可以指定一个首选的 bean。如果没有其他更具体的限定条件,Spring 将优先选择被标记为@Primary
的 bean 进行注入。 - 示例:
// 定义两个相同类型的 bean
@Component
public class ServiceA implements MyService {
//...
}
@Component
@Primary
public class ServiceB implements MyService {
//...
}
@Component
public class Consumer {
@Autowired
private MyService service;
//...
}
在上面的例子中,当
Consumer
类需要注入
MyService
类型的 bean 时,如果没有其他更具体的限定条件,Spring 会优先选择
ServiceB
进行注入,因为它被标记为
@Primary
。
2.@Qualifier
- 作用:当存在多个相同类型的 bean 时,可以使用
@Qualifier
注解结合一个特定的名称来明确指定要注入的 bean。 - 示例:
@Component
public class ServiceA implements MyService {
//...
}
@Component
public class ServiceB implements MyService {
//...
}
@Component
public class Consumer {
@Autowired
@Qualifier("serviceA")
private MyService service;
//...
}
在这个例子中,通过
@Qualifier("serviceA")
明确指定了要注入名为
serviceA
的 bean,也就是
ServiceA
类的实例。
3.@Resource
- 作用:
@Resource
注解是 Java EE 规范中的注解,Spring 也支持该注解进行依赖注入。它可以通过名称或类型进行注入。如果只指定了名称,Spring 会根据名称查找 bean;如果没有指定名称,会根据类型进行注入。 - 示例:
@Component
public class ServiceA implements MyService {
//...
}
@Component
public class ServiceB implements MyService {
//...
}
@Component
public class Consumer {
@Resource(name = "serviceA")
private MyService service;
//...
}
这里通过
@Resource(name = "serviceA")
指定注入名为
serviceA
的 bean,即
ServiceA
类的实例。=
这些注解为解决多个相同类型的 bean 注入问题提供了灵活的方式,可以根据具体的需求选择合适的注解来确保正确的依赖注入。
5、@Autowired和@Resource的区别
- @Autowired是spring框架提供的,@Resource是JDK提供的注解
- @Autowired默认是按类型注入的,而@Resource优先是按照名称注入的,@Resource提供更多的参数设置
@Autowired的装配顺序
👔三、Spring, Spring Boot 和Spring MVC的关系以及区别
1、Spring
** **简单而言是一个开发应用的框架---轻量级,一站式,模块化,母的是用于简化企业级应用程序的开发。
主要功能:管理对象,以及对象之间的依赖关系,面向切面编程,数据库事务管理,数据访问,web框架支持
具有高度可开放性,可以无缝继承第三方框架,不如数据访问框架(Hibernate,JPA),web框架(Status,JSF)
2、Spring Boot
Spring Boot是对Spring的⼀个封装, 为了简化Spring应用的开发而出现的,中小型企业,没有成本研究自己的框架, 使用Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发人员更加专注于Spring应用的开发,而无需过多关注XML的配置和⼀些底层的实现
Spring Boot 是个脚手架, 插拔式搭建项目, 可以快速的集成其他框架进来.
比如想使用SpringBoot开发Web项目, 只需要引入Spring MVC框架即可, Web开发的工作是SpringMVC完成的, 而不是SpringBoot, 想完成数据访问, 只需要引入Mybatis框架即可.
Spring Boot只是辅助简化项目开发的, 让开发变得更加简单, 甚至不需要额外的web服务器, 直接生成jar包执行即可.
3、Spring MVC
Spring MVC是Spring的一个子框架, Spring诞生之后, 大家觉得很好用, 于是按照MVC模式设计了一个 MVC框架(一些用Spring 解耦的组件), 主要用于开发WEB应用和网络接口,所以, Spring MVC 是⼀个Web框架
Spring MVC基于Spring进行开发的, 天生的与Spring框架集成. 可以让我们更简洁的进行Web层开发, 支持灵活的 URL 到页面控制器的映射, 提供了强大的约定大于配置的契约式编程支持, 非常容易与其他视图框架集成,如 Velocity、FreeMarker等
Spring MVC和Spring Boot都属于Spring,Spring MVC 是基于Spring的一个的MVC 框架,而Spring Boot 是基于Spring的⼀套快速开发整合包
欲望以提升热忱,毅力以磨平高山。
🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀
以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐
制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸
版权归原作者 中草药z 所有, 如有侵权,请联系我们删除。