当前位置: 首页 > news >正文

Spring IoCDI

文章目录

  • 一、Spring、Spring boot、Spring MVC之间的区别
  • 1. Spring 是什么
  • 2. 区别概述

一、Spring、Spring boot、Spring MVC之间的区别

1. Spring 是什么

Spring 是包含了众多工具方法的 IoC 容器

(1)容器

容器是用来容纳某种物品的基本装置,比如List/Map就是数据存储容器,Tomcat就是Web容器

(2)loC

1. 概述

loC:Inversion if Control(控制反转),也就是说Spring 是一个“控制反转”的容器,是 Spring 的核心思想

eg. 在类上添加@RestController 和 @Controller 注解,就是把这个对象交给 Spring管理,Spring 框架启动时就会加载该类,即实现了把对象交给Spring管理

在这里插入图片描述
这部分代码就是loC容器做的事

IoC容器的优点
资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

  1. 资源集中管理: IoC容器会帮我们管理一些资源(对象等),我们需要使用时, 只需要从IoC容器中去取就可以了
  2. 我们在创建实例的时候不需要了解其中的细节, 降低了使用资源双方的依赖程度, 也就是耦合度

代码方面理解:把材料外包出去,不自己制造

2. 使用

【1】Bean的存储

Spring 是一个loC容器,而作为容器,那【存】和【取】的功能就是最基本的。
Spring 容器 管理的主要是对象,这些对象, 我们称之为"Bean"。我们把这些对象交由Spring管理, 由Spring来负责对象的创建和销毁. 我们程序只需要告诉Spring,哪些需要存,以及如何从Spring中取出对象

对于 Spring 框架而言,共有两类注解可以将某个对象交给loC容器管理

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

Bean 的 名称:Spring bean 是Spring框架在运行时管理的对象,Spring 会给管理的对象起一个名字,而根据这个名称(BeanId)就可以获取到对应的对象

Bean的命名约定:程序开发人员不需要为bean指定名称(BeanId), 如果没有显式的提供名称(BeanId),Spring容器将为该bean生成唯⼀的名称

命名约定使用Java标准约定作为实例字段名. 也就是说,bean名称以小写字母开头,然后使用驼峰式大小写

  • 类名: UserController, Bean的名称为:userController
  • 类名: AccountManager, Bean的名称为:accountManager

也有⼀些特殊情况, 当有多个字符并且第⼀个和第⼆个字符都是大写时, 将保留原始的大小写

  • 类名: UController, Bean的名称为:UController
  • 类名: AManager, Bean的名称为:AManager

@Controller(控制器存储)

@Controller
public class UserController {public void sayHi(){System.out.println("这是UserController");}
}@SpringBootApplication
public class demo {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(demo.class, args);//从上下文中获取对象,下面是三种不同的获取方式//根据类的类型获取UserController userController1 = context.getBean(UserController.class);//根据名称获取,需要强转UserController userController2 = (UserController) context.getBean("userController");//根据名称和类型获取,不需要强转UserController userController3 = context.getBean("userController", UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);}}

在这里插入图片描述

获取bean对象, 是父类BeanFactory提供的功能

  • ApplicationContext VS BeanFactory(常见面试题)
    • 继承关系和功能方面来说:Spring 容器有两个顶级的接口:BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能力,而ApplicationContext 属于 BeanFactory 的子类,它除了继承了 BeanFactory 的所有功能之外,它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
    • 从性能方面来说:ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,而
      BeanFactory 是需要那个才去加载那个,因此更加轻量。(空间换时间)

@Service(服务存储)

@Service
public class UserService {public void sayHi(){System.out.println("这是UserService");}
}@SpringBootApplication
public class demo {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(demo.class, args);UserService service = context.getBean(UserService.class);service.sayHi();}}

@Repository(仓库存储)、@Configuration(配置存储)、@Component(组件存储)的操作与上述都类似,只需要更改注解

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio//从Spring上下⽂中获取对象UserConfiguration userConfiguration = context.getBean(UserConfiguration.cl//使⽤对象userConfiguration.sayHi();}
}

为什么需要这么多的注解???

让程序员看到类注解之后,就能直接了解当前类的用途

  • @Controller:控制层, 接收请求, 对请求进行处理, 并进行响应
  • @Servie:业务逻辑层, 处理具体的业务逻辑
  • @Repository:数据访问层,也称为持久层. 负责数据访问操作
  • @Configuration:配置层. 处理项目中的⼀些配置信息

应用分层的调用逻辑
在这里插入图片描述
方法注解 @Bean

类注解是添加到某个类上的, 但是存在两个问题:

  1. 使用外部包里的类, 没办法添加类注解
  2. ⼀个类, 需要多个对象,比如多个数据源
    这种场景, 我们就需要使用方法注解 @Bean,@Bean 注解的bean, bean的名称就是它的方法名

使用时的注意点

  • 在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中
  • bean想要生效,还需要被Spring扫描
    • 通过 @ComponentScan 来配置扫描路径
    • 有时候 @ComponentScan 注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication 中了。默认扫描的范围是SpringBoot启动类所在包及其子包
@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo(){UserInfo user = new UserInfo();user.setName("zhangsan");user.setAge(18);return user;}
}

定义多个对象

@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo1(){UserInfo user = new UserInfo();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic UserInfo userInfo2(){UserInfo user = new UserInfo();user.setName("lisi");user.setAge(22);return user;}
}@SpringBootApplication
public class St20231205Application {public static void main(String[] args) {//根据名称获取Bean对象UserInfo userInfo1 = (UserInfo) context.getBean("userInfo1");UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");System.out.println(userInfo1);System.out.println(userInfo2);}}

重命名Bean

@Bean(name = {"u1","user1"})
public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;
}@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

name={} 可以省略,如下代码所示,如:
@Bean({“u1”,“user1”})
public User user1(){
          User user = new User();
          user.setName(“zhangsan”);
          user.setAge(18);
          return user;
}

只有⼀个名称时, {}也可以省略, 如:
@Bean(“u1”)
public User user1(){
          User user = new User();
          user.setName(“zhangsan”);
          user.setAge(18);
          return user;
}

(3)DI

1. 概述

DI: Dependency Injection(依赖注入),即容器在运行期间, 动态的为应用程序提供运行时所依赖的资源,如果程序运行时需要某个资源(对象),此时容器就为其提供这个资源。

所以,DI 和 loC是从不同的角度去描述同一件事情,即都是通过引入loC容器,利用依赖关系注入的方式,实现对象之间的解耦。loC是一种思想,而DI是loC的一种具体实现

依赖注入是⼀个过程,是指IoC容器在创建Bean时, 去提供运行时所依赖的资源,而资源指的就是对象

2. 使用

关于依赖注入,Spring也给我们提供了三种方式:

  1. 属性注入(Field Injection)
  2. 构造方法注入(Constructor Injection)
  3. Setter 注入(Setter Injection)

(1)属性注入

属性注入是使用 @Autowired 实现的,将 Service 类注入到 Controller 类中

@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi() {System.out.println("Hi,UserController");userService.sayHi();}}@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}@SpringBootApplication
public class demo {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(demo.class, args);UserController userController = (UserController)context.getBean("userController");userController.sayHi();}}

(2)构造方法注入

@Controller
public class UserController2 {private UserService userService;@Autowiredpublic UserController2(UserService userService){this.userService = userService;}public void sayHi() {System.out.println("Hi,UserController2");userService.sayHi();}
}

(3)Setter注入

@Controller
public class UserController3 {//注⼊⽅法3: Setter⽅法注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(){System.out.println("hi,UserController3...");userService.sayHi();}
}

(4)三种注入优缺点分析

  • 属性注入
    • 优点: 简洁,使用方便
    • 缺点:
      • 只能用于 IoC 容器,如果是非 IoC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常)
      • 不能注入⼀个Final修饰的属性
  • 构造函数注⼊(Spring 4.X推荐)
    • 优点:
      • 可以注入final修饰的属性
      • 注入的对象不会被修改
      • 依赖对象在使用前⼀定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法
      • 通用性好, 构造方法是JDK支持的, 所以更换任何框架,他都是适用的
    • 缺点:
      • 注入多个对象时, 代码会比较繁琐
  • Setter注入(Spring 3.X推荐)
    • 优点: 方便在类实例之后, 重新对该对象进行配置或者注入
    • 缺点:
      • 不能注入⼀个Final修饰的属性
      • 注入对象可能会被改变, 因为setter方法可能会被多次调用, 就有被修改的风险

(4)@Autowired存在问题

当同⼀类型存在多个bean时,使用@Autowired会存在问题。

解决方法

  1. @Primary:确定默认的实现
@Component
public class BeanConfig {@Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}
  1. @Qualifier:指定当前要注入的bean对象。@Qualifier注解不能单独使用,必须配合@Autowired使用

```java
@Controller
public class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}
  1. @Resource:按照bean的名称进行注入。通过name属性指定要注⼊的bean的名称
@Controller
public class UserController {@Resource(name = "user2")private User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}

@Autowird 与 @Resource的区别

  • @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
  • @Autowired 默认是按照类型注入,而@Resource是按照名称注⼊. 相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean

2. 区别概述

Spring:简单来说,Spring 是⼀个开发应用框架,什么样的框架呢,有这么几个标签:轻量级、⼀站式、模块化,其目的是用于简化企业级应用程序开发

Spring的主要功能: 管理对象,以及对象之间的依赖关系, ⾯向切⾯编程, 数据库事务管理, 数据访问,web框架支持等
但是Spring具备高度可开放性, 并不强制依赖Spring, 开发者可以自由选择Spring的部分或者全
部,Spring可以无缝继承第三方框架,比如数据访问框架(Hibernate 、JPA),web框架(如Struts、JSF)

Spring MVC:Spring MVC是Spring的⼀个子框架, Spring诞生之后,⼤家觉得很好用,于是按照MVC模式设计了⼀个 MVC框架(一些用Spring 解耦的组件), 主要用于开发WEB应用和网络接口,所以,Spring MVC 是⼀个Web框架

Spring MVC基于Spring进行开发的, 天生的与Spring框架集成. 可以让我们更简洁的进行Web层开发, 支持灵活的 URL 到页面控制器的映射, 提供了强大的约定大于配置的契约式编程支持, 非常容易与其他视图框架集成,如 Velocity、FreeMarker等

Spring Boot:Spring Boot是对Spring的⼀个封装, 为了简化Spring应用的开发而出现的,中小型企业,没有成本研究自己的框架, 使用Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发人员更加专注于Spring应用的开发,而无需过多关注XML的配置和⼀些底层的实现

Spring Boot 是个脚⼿架, 插拔式搭建项目, 可以快速的集成其他框架进来

Spring MVC和Spring Boot都属于Spring,Spring MVC 是基于Spring的⼀个MVC 框架,⽽Spring Boot 是基于Spring的⼀套快速开发整合包

http://www.lryc.cn/news/261931.html

相关文章:

  • vue使用el-tag完成添加标签操作
  • ACM-MM2023 DITN详解:一个部署友好的超分Transformer
  • STM32超声波——HC_SR04
  • [Excel] vlookup函数
  • Python入门第5篇(爬虫相关)
  • 单元测试二(实验)-云计算2023.12-云南农业大学
  • Axure动态面板的使用以及示例分享
  • 容斥原理的并
  • JavaSE第7篇:封装
  • mysql数据库相关知识【MYSQL】
  • android studio 创建按钮项目
  • gitee提交代码步骤介绍(含git环境搭建)
  • 【MyBatis-Plus】常用的插件介绍(乐观锁、逻辑删除、分页)
  • DApp测试网络Ganache本地部署并实现远程连接
  • 好用的硬盘分区工具,傲梅分区助手 V10.2
  • 【华为鸿蒙系统学习】- HarmonyOS4.0开发|自学篇
  • Qt图像处理-Qt中配置OpenCV打开本地图片
  • HTML中RGB颜色表示法和RGBA颜色表示法
  • Openwrt源码下载出现“The remote end hung up unexpected”
  • Spring定时任务动态更改(增、删、改)Cron表达式方案实例详解
  • 常用登录加密之Shiro与Spring Security的使用对比
  • 获取文件路径里的文件名(不包含扩展名)
  • HiveSql语法优化二 :join算法
  • Leetcode—459.重复的子字符串【简单】
  • Mac安装Typora实现markdown自由
  • 前后端传参格式
  • 【后端学前端】第三天 css动画 动态搜索框(定位、动态设置宽度)
  • 51.0/表单(详细版)
  • 动态规划(Dynamic Programming)
  • linux使用文件描述符0、1和2来处理输入和输出