Spring两大核心思想 IoC和AoP

news2024/11/18 11:31:44

目录

✨ 一、什么是IoC

1、定义 🎊

2、IoC思想 🎊

3、优势 🎊

4、对象的管理 🎊

存对象:@Component

取对象:@AutoWired 

✨二、什么是DI 

1、定义 🎊

2、IoC和DI的关系🎊

可以说DI是IoC的一种实现

✨三、IoC&DI的使用 

1、实现实例:用@Component注解实现存 🎊

2、 使用@AutoWired注解实现从容器中取对象🎊

✨四、IoC详解 

1、Bean的存储(类注解)🎊

1) @Controller(控制器存储)(控制层,接受请求,对请求进行处理,并进行响应)

从容器中获取对象:Spring上下文

2)@Service(服务存储)(业务逻辑层,处理具体的业务逻辑) 

​编辑 

3)Repository(仓库存储)(数据访问层,也称为持久层,负责数据的访问操作)

4)Component(组件存储)

5)Configuration(配置存储)(配置层,处理项目中的一些配置信息)

 2、Bean的命名🎊

 3、获取bean对象的方法(是父类(BeanFactory)提供的功能)🎊

常见的面试题: ApplicationContext VS BeanFactory

 4、方法注解(@Bean)🎊

1、一个对象的情况 

2、多个对象的情况 

 3、重命名Bean

5、扫描路径🎊

✨五、DI详解 

1、依赖注入的三种方法 🎊

1)属性注入(Field Injection)Autowired

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

3)Setter注入(Setter Jniection)

2、三种注入的优缺点分析 🎊

3、@Autowired存在问题(当同一类型存在多个bean时)🎊


让我们先回顾一下什么是Spring:Spring是一个开源框架,他让我们的开发更简单,简单来说,Spring是包含了众多工具的IoC容器。

那么问题来了,什么是容器?什么是IoC容器?

容器是用来容纳某种物品的(基本)装置

  • List/Map ->数据存储器
  • Tomact -> Web容器

 一、什么是IoC

1、定义 

  Inversion of Control(控制反转),也就是说“Spring”是一个控制反转容器。

当需要某个对象时,传统的开发模式中需要new来创建对象,现在不需要再进行创建了,把创建对象的任务交给容器,由Spring来负责对象的创建和销毁,程序只需要依赖注入(Dependency Injection,DI) 就可以了。

这个容器称为:IoC容器。Spring是一个IoC容器,有时候Spring也称为Spring容器。(容器里面装的是对象,Spring管理的对象称之为bean

2、IoC思想 

     像我们之前写代码,在类上面添加@RestController和@Controller注解,就是把这个对象交给Spring来管理,Spring框架启动时就会加载该类,把对象交给Spring管理,就是IoC思想。 

3、优势 

资源不由使用资源的双方管理,而由不使用资源的第三方管理。

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

4、对象的管理 

  1. 存对象:@Component

  2. 取对象:@AutoWired 

二、什么是DI 

1、定义 

 Dependency Injection,DI(依赖注入),容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。

2、IoC和DI的关系

可以说DI是IoC的一种实现

可以看出,依赖注入和控制反转是从不同的角度的描述同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。 

三、IoC&DI的使用 

1、实现实例:用@Component注解实现存 

@Component
public class BookDao {
    public List<BookInfo> mockBookData() {
        List<BookInfo> bookInfos = new ArrayList<>();
        for(int i = 1;i < 15; i++) {
            BookInfo bookInfo = new BookInfo();
            bookInfo.setId(i);
            bookInfo.setBookName("图书" + i);
            bookInfo.setAuthor("作者" + i);
            bookInfo.setCount(i*15 + 3);
            bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));
            bookInfo.setPublish("出版社" + i);
            bookInfo.setStatus(i%5==0?2:1);
            bookInfos.add(bookInfo);
        }

        return bookInfos;
    }
}
@Component
public class BookService {
    /**
     * 根据数据层返回的结果对数据进行处理
     * @return
     */
    //从Spring中获取对象
    @Autowired
    private BookDao bookDao;
    public List<BookInfo> bookInfoList(){
        List<BookInfo> bookInfos = bookDao.mockBookData();
        for(BookInfo bookInfo: bookInfos) {
            if(bookInfo.getStatus()==1) {
                bookInfo.setStateCN("可借阅");
            }else if(bookInfo.getStatus()==2){
                bookInfo.setStateCN("不可借阅");
            }
        }
        return bookInfos;
    }
}

2、 使用@AutoWired注解实现从容器中取对象

@Autowired
    private BookDao bookDao;

四、IoC详解 

1、Bean的存储(类注解)

通过前面 学习,我们知道了把某个对象交给IoC容器进行管理,需要在类上添加一个注解,而Spring也提供了更丰富的注解。

类注解:@Controller、@Service(服务存储)、@Component(组件存储)、@Repository(仓库存储)、@Configuration(配置存储)

方法注解:@Bean

设置这么多类注解目的是为了让程序员看到类注解之后,就直接了当的了解当前类的用途

1) @Controller(控制器存储)(控制层,接受请求,对请求进行处理,并进行响应)

看下面例子:使用 @Controller存储bean的代码

package com.example.example1.controller;

import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    public void sayHi() {
        System.out.println("祝你好运,小李");
    }
}

如何观察这个对象已经存在在Spring容器中了呢?

@SpringBootApplication
public class Example1Application {

    public static void main(String[] args) {
        //获取Spring上下文对象
       ApplicationContext context = SpringApplication.run(Example1Application.class, args);
       //从Spring上下文中获取对象
        UserController userController = context.getBean(UserController.class);
        //使用对象
        userController.sayHi();
    }

}

运行程序: 

但如果删除@Controller,观察运行结果: 

 

从容器中获取对象:Spring上下文

 上下文:就是指当前的运行环境,也可以看做是一个容器,容器里面存了很多内容,这些内容是当前的运行的环境。

ApplicationContext context = SpringApplication.run(Example1Application.class, args);

2)@Service(服务存储)(业务逻辑层,处理具体的业务逻辑) 

package com.example.example1.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void sayHi() {
        System.out.println("祝你幸福快乐,小李");
    }
}
  //获取Spring上下文对象
       ApplicationContext context = SpringApplication.run(Example1Application.class, args);       
       UserService userService = context.getBean(UserService.class);
       userService.sayHi();

 

3)Repository(仓库存储)(数据访问层,也称为持久层,负责数据的访问操作)

4)Component(组件存储)

5)Configuration(配置存储)(配置层,处理项目中的一些配置信息)

 2、Bean的命名

程序开发人员不需要为bean指定名称 ,如果没有显示的提供名称,Spring容器将为该Bean生成唯一的名称

来看spring官方文档中说明:Bean Overview :: Spring Framework

 

 3、获取bean对象的方法(是父类(BeanFactory)提供的功能)

package com.example.example1;

import com.example.example1.controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Example1Application {

    public static void main(String[] args) {
        //获取Spring上下文对象
       ApplicationContext context = SpringApplication.run(Example1Application.class, args);
       //从Spring上下文中获取对象,根据类型
        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);
    }

}

 

常见的面试题: ApplicationContext VS BeanFactory

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

 4、方法注解(@Bean)

考虑以下场景:1、使用外部包里面的类,没办法添加类注解

2、一个类,需要多个对象,比如多个数据源 

1、一个对象的情况 

 示例:

package com.example.example1.bean;

import lombok.Data;

import javax.lang.model.element.NestingKind;
@Data
public class User {
    private String name;
    private int age;
}
package com.example.example1.bean;
import org.springframework.context.annotation.Bean;

public class BeanConfig {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(12);
        return user;
    }
}

 

User user = context.getBean(User.class);
        System.out.println(user);

 让我查看运行结果,结果报错了

什么原因造成的呢?

在Spring框架的设计中,方法注解@Bean要配合类注解才能将对象正常的存储到Spring容器中

对上述代码进行修改

package com.example.example1.bean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class BeanConfig {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(12);
        return user;
    }
}

再次运行:

2、多个对象的情况 

 

从运行结果可以看出:@Bean注解的Bean,bean名称就是它的方法名

所以我们根据名称来获取bean对象 

 3、重命名Bean

    @Bean(name = {"u3","user3"})
    public User user3(){
        User user = new User();
        user.setName("wangwu");
        user.setAge(14);
        return user;
    }
 User u3 = (User) context.getBean("u3");
        System.out.println(u3);

 

5、扫描路径

问题:使用前面学过的四个注解声明Bean,一定会生效吗?

答案是不一定的,bean要想生效,还需要被Spring扫描 

  1. 通过@CompontentScan 

@ComponentScan({"com.example.example1"}) 

五、DI详解 

 依赖注入是一个过程,是指IoC在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象,之前,我们使用@Autowired这个注解,完成了依赖注入的操作

简单来说,就是把对象取出来放到某个类属性中

1、依赖注入的三种方法 

1)属性注入(Field Injection)Autowired

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi() {
        System.out.println("祝你好运,小李");
        userService.sayHi();
    }
}

 

@Service
public class UserService {
    public void sayHi() {
        System.out.println("祝你幸福快乐,小李");
    }
}
      UserController userController = (UserController) context.getBean("userController");
        userController.sayHi();

 

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

 

package com.example.example1.controller;

import com.example.example1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController2 {
    private UserService userService;
    @Autowired
    public UserController2 (UserService userService) {
        this.userService = userService;
    }
    public void sayHi() {
        System.out.println("祝你好运,小李");
        userService.sayHi();
    }
}

注意:如果类只有一个构造方法,那注解可以省略,反之则不行 

3)Setter注入(Setter Jniection)

2、三种注入的优缺点分析 

• 属性注⼊ ◦:

优点: 简洁,使⽤⽅便;

◦ 缺点: ▪ 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指 针异常) ▪ 不能注⼊⼀个Final修饰的属性

• 构造函数注⼊(Spring 4.X推荐)

◦ 优点: ▪ 可以注⼊final修饰的属性 ▪ 注⼊的对象不会被修改 ▪ 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法. ▪ 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

◦ 缺点: ▪ 注⼊多个对象时, 代码会⽐较繁琐

• Setter注⼊(Spring 3.X推荐)

◦ 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊

◦ 缺点: ▪ 不能注⼊⼀个Final修饰的属性 ▪ 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险. 

3、@Autowired存在问题(当同一类型存在多个bean时)

@Autowird 与 @Resource的区别

• @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解

• @Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊.

相⽐于 @Autowired 来说, @Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1882513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

广东行政职业学院数据智能订单班开班暨上进双创工作室签约仪式圆满结束

为响应教育领域数字化与智能化浪潮这一变革&#xff0c;给学生提供更好的教育资源和实践机会&#xff0c;6月27日&#xff0c;“泰迪广东行政职业学院数据智能订单班开班仪式暨上进双创工作室签约授牌”在广东行政职业学院举行。广东行政职业学院智慧政务学院&#xff08;电子信…

JAVA里的object类

public static String toString(Object o) // 获取对象的字符串表现形式 public static boolean equals(Object a, Object b) // 比较两个对象是否相等 public static boolean isNull(Object obj) // 判断对象是否为null pu…

数据库断言-数据库连接池

原因&#xff1a;现在的代码是单线程&#xff0c;如果遇到大并发的话就会崩溃&#xff0c;数据库查询就查不过来 措施&#xff1a;需要建立数据库连接池&#xff0c;可以设置连接池的数量 什么是大并发&#xff1a;很多客户端在idea写的程序和数据库建立连接 步骤&#xff1…

Python处理异常用操作介绍

Python中的异常处理主要用于捕获和处理程序运行过程中出现的错误。 在编写Python程序时&#xff0c;我们经常会遇到各种错误&#xff0c;如语法错误、运行时错误等。为了确保程序的稳定性和健壮性&#xff0c;我们需要对可能出现的错误进行捕获和处理。本文将介绍Python中常用的…

css美化滚动条样式

效果展示 实现 滚动条宽&#xff0c;高度 /* 整体滚动条 */ ::-webkit-scrollbar {width: 10px; }/* 滚动条轨道 */ ::-webkit-scrollbar-track {background-color: #ffffff;border-radius: 6px; }/* 滚动条滑块 */ ::-webkit-scrollbar-thumb {background-color: #888;borde…

伺服阀放大器配套稳压电源

稳压电源是为伺服阀放大器配套的电源。该稳压电源在开关电源基础上采用了多项先进技术进行设计&#xff0c;输出直流电压稳压精度高、纹波系数小、可靠性好。稳压电源也适用于其他各种伺服控制系统的配套电源。输入&#xff08;180~240VAC 50Hz&#xff09;&#xff0c;输出&am…

SAP ABAP 常用实用函数

文章目录 前言一、日期 时间 相关 a.两个日期之间相隔多少月 二、数据 操作 转化 加密 a.增加 去除 前导零 b.将 数值类型 负号 提前 c.数据加密 MD5 加密 三、获取 属性 定义 读取 数据 a.获取函数的 出参 入参 定义 …

Linux|如何查找和删除重复文件

引言 整理您的个人文件夹甚至整个操作系统可能会相当棘手&#xff0c;特别是当您习惯于使用下载管理器从网上下载各种资料时。 在很多情况下&#xff0c;您可能会发现自己不小心下载了重复的mp3、pdf和epub文件&#xff08;以及其他类型的文件&#xff09;&#xff0c;并将它们…

HTML5+CSS3+JS小实例:图片九宫格

实例:图片九宫格 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1…

智慧城市新利器:免费可视化工具助力高效管理

在智慧城市的建设中&#xff0c;实现高效的统筹管理是至关重要的。通过免费可视化工具“山海鲸可视化”&#xff0c;这一目标可以轻松达成。山海鲸可视化是一款免费可视化工具&#xff0c;具备二三维融合、易用性、安全性以及高质量画面渲染等特色&#xff0c;是制作智慧城市可…

通义听悟--一个懂你的AI助理

通义听悟--一个懂你的AI助理 通义听悟音频转文字本地音视频转文字云盘音视频转文字 实时记录通义听悟进阶体验感受功能建议产品联动 通义听悟 在体验通义听悟之前&#xff0c;我们首先得知道什么是通义听悟&#xff1f;有什么应用场景&#xff1f; 通义听悟简单来说就是你的工…

Java短剧系统

探索影视新体验 &#x1f4f1;一、引言&#xff1a;短剧时代的来临 在数字化的今天&#xff0c;我们见证了许多内容消费模式的转变。从长篇大论的电视剧到短小精悍的短视频&#xff0c;再到如今备受瞩目的短剧&#xff0c;观众对于影视内容的需求越来越多元化。而短剧系统微信…

Es结合springboot(笔记回忆)

导包 <!--导入es--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency><groupId>org.springframework.boot<…

前端vue项目升级nodejs后无法运行了

问题描述&#xff1a; 运行、打包都正常的vue项目&#xff0c;在将nodejs升级到v20.14.0后&#xff0c;均报错了&#xff1a; Error: error:0308010C:digital envelope routines::unsupported opensslErrorStack: [ error:03000086:digital envelope routines::initializ…

Centos下rpm和yum执行卡住问题(已解决)

问题描述 执行rpm和yum卡住&#xff0c; 没有任何报错信息&#xff0c;且无法 ctrl c 终止&#xff0c;只能通过后台 kill -9 杀死。 问题排查&#xff1a; 查看yum日志&#xff1a;yum -vv 软件包 会发现卡在 loading keyring from rpmdb&#xff0c;即load DB存在问题。 …

Java - 程序员面试笔记记录 实现 - Part2

2.1 输入输出流 流可以被看作一组有序的字节集合&#xff0c;即数据在两个设备间的传输。 字节流&#xff1a;以字节作为单位&#xff0c;读到一个字节就返回一个字节&#xff1b;InputStream & OutputStream。 字符流&#xff1a;使用字节流读到一个到多个字节先查询码…

【技巧】ArcGIS Pro设置自动保存数据编辑内容

一、工程文件自动保存 ArcGIS Pro软件的工程也可以自动保存备份。默认备份时间是5分钟&#xff0c;您可以在【工程】→【选项】→【常规】→【工程恢复】中调整自动备份时间。 二、数据编辑自动保存 操作方法&#xff1a;【工程】→【选项】→【编辑】→【会话】&#xff0c;勾…

安卓app开发-基础-本地环境安装android studio且配置参数

安卓app开发-基础-本地环境安装android studio且配置参数&#xff01;今天为大家介绍一下&#xff0c;如何在自己本地电脑安装android ,studio和启动一个简单的java版本的项目。 第一步&#xff0c;去下面的地址&#xff0c;下载一个安装文件。 地址&#xff1a;AndroidDevToo…

Stable Diffusion 商业变现与绘画大模型多场景实战

前言 ai绘画软件Stable Diffusion是一种通过模拟扩散过程&#xff0c;将噪声图像转化为目标图像的文生图模型&#xff0c;具有较强的稳定性和可控性&#xff0c;可以将文本信息自动转换成高质量、高分辨率且视觉效果良好、多样化的图像。在日常工作中&#xff0c;ai绘画软件St…

(3)Java 8 实战第二版——使用流和Lambda进行高效编程

集合工厂 List<String> friends Arrays.asList("Raphael", "Olivia"); friends.set(0, "Richard"); friends.add("Thibaut"); ←---- 抛出一个UnsupportedModificationException异常通过工厂方法创建的Collection的底层…