SpringIOCDI—第一讲

文章目录

  • 什么是IOC
    • 什么是控制,谁控制谁
    • 什么是反转,从什么反转到什么了
  • IOC的注解
    • 五大类注解
      • @Controller注解(控制器存储)
      • @Service(服务存储)
      • @Repository(仓库存储)
      • @Componet(组件存储)
      • @Configuration(配置存储)
    • 为什么这么多注解?
    • 类注解之间的关系
    • Bean的命名规则
    • 什么是方法注解(@Bean)
      • Bean注解
      • Bean的重命名
  • 什么是DI
    • @Autowired注解的局限性
      • @Primary注解
      • @Primary注解
      • @Resource
    • DI注入的方式
      • 构造方法注入
      • Setter方式注入

什么是IOC

IOC中文叫做控制反转,这是一种设计思想,那么什么是控制反转呢?想明白这个概念我们就要搞明白这两个概念

什么是控制,谁控制谁

首先是第一个概念谁控制谁呢?首先我们先搞明白谁是被控制的一方,在这里被控制的一方就是我们的各种对象,那么在传统的javaSE的程序设计中,我们创建对象是通过new来进行创建的,而IOC是有一个专门的容器来进行这些对象的创建和管理。因此这里的控制指的就是对我们创建对象的控制。那么回到那个问题谁控制了谁?:答案很明显了,是IOC容器控制了对象,控制了什么呢?控制了外部资源的获取

什么是反转,从什么反转到什么了

那么什么是反转呢?在传统的应用程序中是由我们自己在对象中主动控制获取依赖对象而反转的含义的就是由容器帮助我们进行对象的创建和存取。那么Spring想要帮我们进行存取对象该怎么做呢?答案是通过注解的形式

IOC的注解

想要将对象存储在spring中有两种方式来实现
1、首先是可以通过类注解的形式
2、可以通过方法注解的形式

五大类注解

首先就是五大类注解,这几个类注解都有哪些呢?分别是如下注解

@Controller注解(控制器存储)

该注解的使用方式如下

package com.example.spring_ioc;

import org.springframework.stereotype.Controller;

@Controller
public class UserControl {
    public void doUserControl(){
        System.out.println("doUserControl ....");
    }
}

首先我们先写出一个被controller注解的类,然后我们来进行获取bean

package com.example.spring_ioc;

import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
//然后在程序上下文中进行调用。
@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
       ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);
       UserControl userControl=context.getBean(UserControl.class);
       userControl.doUserControl();
    }

}

那么上面就是我们通过@Controller注解进行修饰之后得到的程序,这里我们来进行运行一下来看看
在这里插入图片描述
这里我们发现我们的程序运行起来了。

@Service(服务存储)

在用法上大致相同我们来看一下代码

package com.example.spring_ioc;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void doUser(){
        System.out.println("doUser ....");
    }
}

那么有了上面的用列我想大家也能推到出来其余的三个注解在使用上也是大差不差的。

@Repository(仓库存储)

package com.example.spring_ioc;

import org.springframework.stereotype.Repository;

@Repository
public class ResponceUser {
    public void doRespository(){
        System.out.println("doRepository ....");
    }
}

@Componet(组件存储)

package com.example.spring_ioc;

import org.springframework.stereotype.Component;

@Component
public class ComponetUser {
    public void doComponet(){
        System.out.println("doComponetuser .....");
    }
}

@Configuration(配置存储)

package com.example.spring_ioc;

import org.springframework.context.annotation.Configuration;

@Configuration
public class ConfigurationUser {
    public void doConfiguration(){
        System.out.println("@Configuration ...");
    }
}

为什么这么多注解?

相信看到这里很多人会对这里有个疑惑,既然用法和作用都差不多为什么还要有这么多注解?直接就弄一个不就可以了吗?其实这是因为这个东西就跟我们的车牌号是一个道理的,在我们车牌号中我们不同的城市我们的车牌号的前面两个字符是不一样的,那么为什么这样做呢?这样做除了说是节约号码之外还有一个好处就是我们可以通过车牌迅速的确定这个车辆是哪个地方的,比如说你看到了豫A那么你第一个想到的就是河南郑州。这是类似的,有了这些注解也可以帮助我们开发者人员迅速知道这块代码是哪一层的。作用是什么。那么说到这里就涉及到了我们的工程分层。分层图如下所示
在这里插入图片描述

类注解之间的关系

在这里插入图片描述
通过查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:这些注解都有一个@Component注解。说明他们本身就属于@Component的子类。

Bean的命名规则

这里为什么要提到Bean的命名规则呢?因为我们在获取Bean对象的时候其实我们也是可以通过类的名称来进行获取的而名称获取就需要一定的规则来规范你所命名的名称了。
如下在这里插入图片描述
首先我们有图中的这些类,这些类的命名呢都是首字母大写那么我们根据这些类的名称去获取的时候我们应该怎么遵循什么规则去获取呢?那么代码如下

package com.example.spring_ioc;

import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
       ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);
       ConfigurationUser configurationUser=(ConfigurationUser)context.getBean("configurationUser");
       configurationUser.doConfiguration();
    }
}

这里我们可以看到我们需要给首字母大写转换为小写,此外假如说你的类名称前两个首字母都是大写的话那就不需要转换了,转换后甚至有可能出粗呢。

什么是方法注解(@Bean)

讲完上面的五大注解之后我们来谈一下什么是bean,bean的作用是什么。我们上面说了五大注解是加在了类上的因此叫做类注解,而bean则是方法上的。那么他们直接有什么区别呢?这里先思考一个问题,在上面我们通过类注解去进行了获取对象等,那么这里我们获取到的对象是同一个对象吗?也就是假如说我们对同一个类获取了两次对象那么这两个对象是同一个吗?我们来看一下吧。

package com.example.spring_ioc;

import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
       ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);
        ConfigurationUser configurationUser=(ConfigurationUser) context.getBean("configurationUser");
        ConfigurationUser configurationUser11=context.getBean(ConfigurationUser.class);
        System.out.println(configurationUser11==configurationUser);
    }

}

那么我们来看一下这个代码的运行结果吧
在这里插入图片描述
很明显结果是为true也就是说这里创建出来的两个对象是同一个对象,可是我们在实际开发中有很多情况肯定是不希望这样的那么这时候就需要用到bean注解了。

Bean注解

首先我们先来看一下代码如何操作

package com.example.spring_ioc.Control;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class TestControl {
    public void doCOntrol(){
        System.out.println("docontrol .....");
    }
    @Bean
    public TestControl control(){
        TestControl control=new TestControl();
        return control;
    }
    @Bean
    public TestControl control1(){
        TestControl control1=new TestControl();
        return control1;
    }
}

然后我们来看一下如何获取到对象

package com.example.spring_ioc;

import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
       ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);
       TestControl control=context.getBean(TestControl.class);
       control.doCOntrol();
    }

}

在这里插入图片描述
这里我们可以发现我们想要继续通过之前的方法去获取对象是不行的了,那么他报错的原因也很简单那就是他不知道该获取哪个对象,就像一个班级里面有很多个男生,你直接就喊出来一个男生,这时候肯定会懵一下感到疑惑你找谁啊?所以代码也是这样的那么该怎么办呢?答案就是通过名称获取

package com.example.spring_ioc;

import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
       ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);
       TestControl control=(TestControl) context.getBean("control");
       TestControl control1=(TestControl)context.getBean("control1");
       System.out.println(control1==control);
       control.doCOntrol();
       control1.doCOntrol();
    }

}

那么我们来看一下运行的结果如何
在这里插入图片描述
我们发现这里的运行结果表明我们创建出来的两个对象是不同的两个对象

Bean的重命名

使用Bean注解是可以对类进行重命名的,那么如何进行重命名呢?我们来看一下代码

package com.example.spring_ioc.Control;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class TestBean {
    @Bean("u1")
    public TestBean testBean1(){
        TestBean testBean=new TestBean();
        return testBean;
    }
    public void run(){
        System.out.println("runTestBean");
    }
}

那么这时候我们想要获取对象就可以通过重命名之后的名字进行获取了

什么是DI

那么接下来什么是DI呢?DI也叫做属性注入,什么是属性注入?我们来看一下下面的这个代码
TestDI

package com.example.spring_ioc.Control;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Configuration
public class TestDI {
    @Autowired
    Person person;
    @Bean
    public TestDI t(){
        TestDI testDI=new TestDI();
        return testDI;
    }
    public void run(){
        System.out.println("+++");
    }

}

Person

package com.example.spring_ioc.Control;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@ToString
@Controller
public class Person {
    public String name="zyfcl";
    public Integer age=20;

    @Bean
    public Person p(){
        Person person=new Person();
        return person;
    }
}

从上面两个代码也许就能看出来,首先Person是我们的一个Controller类,也就是已经注入了spring容器中了并且使用Bean将p方法进行注解,此时就相当于告诉了spring我们这个类的对象调用的是我们的这个方法进行获取,然后在TestDI类中我们使用了person类创建的person对象,并且这个对象使用了Autowired注解,也就是会进行注入。

@Autowired注解的局限性

首先我们要明白@Autowired注解的匹配原则首先他是先按照类型进行匹配的但是这样势必会有下面的这个问题那就是假如说类型匹配上了但是我们使用了@Bean注解注解了多个方法去进行创造这个对象,那么到底该返回哪一个呢?如下代码


package com.example.spring_ioc.Control;

import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@ToString
@Configuration
public class Person {
    public String name;
    public Integer age;
    @Bean
    Person person1(){
        Person person2=new Person();
        person2.age=21;
        person2.name="cl";
        return person2;
    }

    @Bean
    public Person person2(){
        Person person1=new Person();
        person1.name="zyf";
        person1.age=19;
        return person1;
    }
}

package com.example.spring_ioc.Control;

import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@ToString
@Configuration
public class Person {
    public String name;
    public Integer age;
    @Bean
    Person person1(){
        Person person2=new Person();
        person2.age=21;
        person2.name="cl";
        return person2;
    }

    @Bean
    public Person person2(){
        Person person1=new Person();
        person1.name="zyf";
        person1.age=19;
        return person1;
    }
}
package com.example.spring_ioc.Control;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestDI {
    @Autowired
    UserInfo userInfo;
    @Autowired
    Person person;
    @Bean
    public TestDI t(){
        TestDI testDI=new TestDI();
        return testDI;
    }
    public void run(){
        System.out.println("+++");
        System.out.println(person);
    }

    public void  run2(){
        System.out.println(userInfo);
    }

}

那么结合上面的两段代码我们来想一想,这里会不会报错呢?这个person该实例化为哪个呢?其实这里spring也不知道,那么最终怎么办呢?有些情况下可能会报错,有些情况下可能会给你初始为空。我这边是初始为空的。
那么上面的情况怎么解决呢?那就是下面三个注解
首先第一个

@Primary注解

这个注解可以理解为默认的意思也就是出现了上面的情况的话那么就会默认为被这个注解修饰的那种方法。
在这里插入图片描述

@Primary注解

第二种就是这样的注解,表示你想要将其使用哪个对象,在这里面写入你希望的方法名称即可
在这里插入图片描述

@Resource

第三种就是Resource注解它的用法和primary是差不多的都是自己指定。
在这里插入图片描述

DI注入的方式

上面只讲了属性注入实际上我们还有别的方式进行注入

构造方法注入

在这里插入图片描述

这里就是构造的方式注入

Setter方式注入

这里也就相当于写了一个set方法进行了注入。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型实战——最小化agent

1. agent是什么 大模型拥有语言理解和推理能力后,就相当于拥有了大脑,要让模型发挥更大的潜力,就需要给它安装上手臂,让它拥有行动的能力。 而Agent就是一个将语言模型和外部工具结合起来的智能体,它使用语言模型的推…

安全设计 | Microsoft 威胁建模工具Threat Modeling Tool安装及使用详解(文末附样例)

1. 概览 微软威胁建模工具(Threat Modeling Tool)是 Microsoft 安全开发生命周期 (SDL,Security Develop LifeCycle) 的核心要素。 当潜在安全问题处于无需花费过多成本即可相对容易解决的阶段,软件架构师可以使用威胁建模工具提…

人工智能再现大脑细胞导航的活动模式

人工智能再现大脑细胞导航的活动模式 李升伟 编译 深度学习算法可自发模拟特殊神经元的活动,这种神经元活动可以告诉我们在空间的位置。 大鼠使用被称为网格细胞的大脑细胞帮助它们导航,人工智能程序已经可以再现这种能力。 科学家已经使用人工智能来再…

【STM32+k210项目】基于AI技术智能语音台灯的设计(完整工程资料源码)

视频演示 基于AI技术智能语音台灯的设计 前言: 随着社会的快速发展,人们对家用电器智能化程度的要求越来越高。不管是对于学生人群还是对于工作加班者,台灯是每家每户必不可少的工具,长期处于光线太强或者过弱的环境中学习和一系列…

用户账户的权限管理

用户账户的权限管理 用户账号: 1、超级用户 :管理员账号 root 默认对本机拥有最高权限的账户,在系统中唯一。 2、普通用户:一般由管理员创建,拥有的权限是受限制的,一般只在自己的家目录中拥有完整的权限…

每日练习之排序——链表的合并;完全背包—— 兑换零钱

链表的合并 题目描述 运行代码 #include<iostream> #include<algorithm> using namespace std; int main() { int a[31];for(int i 1;i < 30;i)cin>>a[i];sort(a 1,a 1 30);for(int i 1;i < 30;i)cout<<a[i]<<" ";cout&…

走进创新高地,探索职业未来——记大学生参观刺掌信息科技学习活动

在这个向阳生长&#xff0c;充满活力的5月&#xff0c;一群来自江苏大学的充满朝气与求知欲的大学生们来我司参观学习&#xff0c;他们带着对网络安全的热爱和职业生涯的憧憬&#xff0c;走进我们的企业&#xff0c;开始了探索之旅。 交流会上&#xff0c;江苏刺掌信息科技有限…

Python使用multiprocessing实现多进程

大家好&#xff0c;当我们工作中涉及到处理大量数据、并行计算或并发任务时&#xff0c;Python的multiprocessing模块是一个强大而实用的工具。通过它&#xff0c;我们可以轻松地利用多核处理器的优势&#xff0c;将任务分配给多个进程并同时执行&#xff0c;从而提高程序的性能…

CTFHUB技能树——SSRF(二)

目录 上传文件 ​FastCGI协议 Redis协议 上传文件 题目描述&#xff1a;这次需要上传一个文件到flag.php了.祝你好运 index.php与上题一样&#xff0c;使用POST请求的方法向flag.php传递参数 //flag.php页面源码 <?phperror_reporting(0);if($_SERVER["REMOTE_ADDR&…

“从根到叶:使用决策树导航数据”

目录 一、说明 二、什么是决策树&#xff1f; 三、基本概念&#xff1a; 四、工作原理&#xff1a; 五、分类原理分析 5.1 信息熵&#xff1a; 5.2 信息增益&#xff1a; 5.3 基尼杂质&#xff1a; 5.4 基尼系数和熵的区别&#xff1a; 六、对于回归决策树&#xff1a; 6.1 均方…

OR-Oncology Research 肿瘤学研究

文章目录 一、期刊简介二、征稿信息三、期刊表现四、投稿须知五、投稿咨询 一、期刊简介 Oncology Research以临床前和临床癌症治疗为特色&#xff0c;发表了高质量的同行评审研究&#xff0c;有助于在分子生物学、细胞生物学、生物化学、生物物理学、遗传学、生物学、内分泌学…

128天的创意之旅:从初心到成就,我的博客创作纪念日回顾

文章目录 &#x1f680;机缘&#xff1a;初心的种子——回望创作之旅的启航&#x1f308;收获&#xff1a;成长的果实——128天创作之旅的宝贵馈赠❤️日常&#xff1a;创作与生活的交织&#x1f44a;成就&#xff1a;代码的艺术&#x1f6b2;憧憬&#xff1a;未来的蓝图 &…

【RabbitMQ】SpringAMQP--消息转换器

SpringAMQP–消息转换器 测试发送Object类型消息 1.声明队列 Configuration public class FanoutConfig {Beanpublic Queue objectQueue(){return new Queue("object.queue");} }运行消费者后&#xff1a; 2.发送消息 RunWith(SpringRunner.class) SpringBootTes…

01.爬虫---初识网络爬虫

01.初识网络爬虫 1.什么是网络爬虫2.网络爬虫的类型3.网络爬虫的工作原理4.网络爬虫的应用场景5.网络爬虫的挑战与应对策略6.爬虫的合法性总结 1.什么是网络爬虫 网络爬虫&#xff0c;亦称网络蜘蛛或网络机器人&#xff0c;是一种能够自动地、系统地浏览和收集互联网上信息的程…

物联网应用开发--STM32与机智云通信(ESP8266 Wi-Fi+手机APP+LED+蜂鸣器+SHT20温湿度传感器)

实现目标 1、熟悉机智云平台&#xff0c;会下载APP 2、熟悉新云平台创建产品&#xff0c;项目虚拟调试 3、掌握云平台生成MCU代码&#xff0c;并移植。机智云透传固件的下载 4、具体目标&#xff1a;&#xff08;1&#xff09;注册机智云平台&#xff1b;&#xff08;2&…

数据结构~~二叉树-堆

目录 一、基本概念 树的概念 二叉树-堆的概念 二、堆的结构 三、堆排序 向上调整建堆 向下调整建堆 四、TOP-K 五、完整代码 六、总结 一、基本概念 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关…

在ubuntu中查询与某脚本或某设备相关的进程,ps,pgrep,lsof,fuser,pstree,htop命令的使用指南

一、查询与脚本有关的进程 1. 用ps命令 在 Ubuntu 系统中&#xff0c;如果你想查询与特定 Python 脚本 abc.py 相关的线程&#xff0c;你可以使用 ps 命令和 grep 命令结合来查找。ps 命令用于显示当前运行的进程状态&#xff0c;而 grep 命令可以帮助你过滤出包含指定字符串…

(六)DockerCompose安装与配置

DockerCompose简介 Compose 项目是 Docker 官方的开源项目&#xff0c;负责实现对 Docker 容器集群的快速编排。使用前面介绍的Dockerfile我们很容易定义一个单独的应用容器。然而在日常开发工作中&#xff0c;经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现…

Docker Desktop安装和如何在WSL2中使用Docker

最近在使用WSL的过程中&#xff0c;想使用docker遇到了一些问题&#xff0c;在WSL中安装Linux版本的docker&#xff0c;启动镜像之后不能从Windows机器的端口映射出来&#xff0c;查了一圈之后&#xff0c;发现应该使用Docker Desktop软件&#xff0c;下面是安装和使用的方式 …

error1310 写入文件时发生错误,请确认您是否有访问权限 也可能出现error 1304 :写入文件时出错

一般错误提示如下 error1310 Error writing to file 错误 1310 &#xff1a;写入文件时出错&#xff1a;请确认您有权访问该目录&#xff0c; error1304 Error writing to file 错误 1304 &#xff1a;写入文件时出错&#xff1a;请确认您有权访问该目录 1.首先我们退出所…