前端工程师是做网站,网站建设制作汕头,互联网营销案例,广州建设网站技术文章目录 1.Ioc - 控制反转(解耦)1.1传统开发1.2批量生产车轮(修改代码) - 传统方式#xff0c;繁琐1.3解耦1.3.1使用Ioc方法后1.3.2添加变量颜色 只需要修改Tire即可 1.4Bean的存储1.4.1Controller(控制器存储)1.4.2Service(服务存储)1.4.2.1根据context来获取bean1.4.2.2根据… 文章目录 1.Ioc - 控制反转(解耦)1.1传统开发1.2批量生产车轮(修改代码) - 传统方式繁琐1.3解耦1.3.1使用Ioc方法后1.3.2添加变量颜色 只需要修改Tire即可 1.4Bean的存储1.4.1Controller(控制器存储)1.4.2Service(服务存储)1.4.2.1根据context来获取bean1.4.2.2根据名称来获取bean1.4.2.3根据名称和类型获取bean1.4.2.4特殊情况-类名前两位都大写bean的名称为类名 1.4.3Repository (仓库存储)1.4.4Component (组件存储)1.4.5Configuration (配置存储)1.4.6为什么要这么多类注解 - 五大注解1.4.7Controller和其他注解的区别1.4.8Bean 使用1.4.8.1Bean正常使用举例1.4.8.2测试Bean传递参数是如何选择的 1.4.9启动类位置关系影响 1.5 Bean命名1.6Bean取 2.DI - 依赖注入2.1属性注入2.1.1属性注入流程2.1.2属性注入问题 2.2构造方法注入2.2.1只存在一个构造函数时2.2.2存在多个构造函数时 2.3Setter方法注入2.4三种注入优缺点分析2.5Autowired存在问题2.5.1.属性名和你需要使用的对象名保持一致2.5.2.使用Primary注解标识默认的对象2.5.3.使用Qualifier2.5.4 使用 Resource 注解 2.6常见面试题 - Autowird 与 Resouce的区别 3.Ioc、DI、AOP的关系2.6常见面试题 - Autowird 与 Resouce的区别 3.Ioc、DI、AOP的关系 大家好我是晓星航。今天为大家带来的是 Ioc和DI 相关的讲解
1.Ioc - 控制反转(解耦)
1.1传统开发
软件设计原则高内聚低耦合。
高内聚一个模块内部的关系
低耦合各个模块之间的关系
我们的实现思路是这样的:
先设计轮子(Tire)然后根据轮子的大小设计底盘(Bottom)接着根据底盘设计车身(Framework)最后根据车身设计好整个汽车(Car)。这里就出现了一个依赖关系: 汽车依赖车身车身依赖底盘底盘依赖轮子. 最终程序的实现代码如下
Main.java
package com.example.demo.ioc;/*** Created with IntelliJ IDEA* Description* User: 晓星航* Date: 2024 -03 -15* Time: 20:16*/
public class Main {public static void main(String[] args) {Car car new Car(17);car.run();Car car2 new Car(19);car2.run();}
}Car.java
package com.example.demo.ioc;/*** Created with IntelliJ IDEA* Description* User: 晓星航* Date: 2024 -03 -15* Time: 20:16*/
public class Car {private Framework framework;public Car(int size) {framework new Framework(size);System.out.println(car init...);}public void run() {System.out.println(car run);}
}FrameWork.java
package com.example.demo.ioc;/*** Created with IntelliJ IDEA* Description* User: 晓星航* Date: 2024 -03 -15* Time: 20:17*/
public class Framework {private Bottom bottom;public Framework(int size) {bottom new Bottom(size);System.out.println(framework init...);}
}Bottom.java
package com.example.demo.ioc;/*** Created with IntelliJ IDEA* Description* User: 晓星航* Date: 2024 -03 -15* Time: 20:19*/
public class Bottom {private Tire tire;public Bottom(int size) {tire new Tire(size);System.out.println(bottom init...);}
}Tire.java
package com.example.demo.ioc;/*** Created with IntelliJ IDEA* Description* User: 晓星航* Date: 2024 -03 -15* Time: 20:20*/
public class Tire {private int size;public Tire(int size) {this.size size;System.out.println(tire init...size size);}
}输出结果 1.2批量生产车轮(修改代码) - 传统方式繁琐
我们为了批量化生产各种型号的车轮胎继而修改了Tire类中的size变量为默认值传参到Tire中这就导致了Bottom的关联问题。 在将参数int size传到Bottom中之后Tire不报错了但是Bottom又出现了关联问题 在将参数int size传到Framework中之后Bottom不报错了但是Framework又出现了关联问题
在将参数int size传到Car中之后Framework不报错了,此时Car中可以正常批量化生产各种型号的车轮的车了
使用Component和Autowired来简化代码 Component 标注Spring管理的Bean使用Component注解在一个类上表示将此类标记为Spring容器中的一个Bean
Autowired 是一个注释它可以对类成员变量、方法及构造函数进行标注让 spring 完成 bean 自动装配的工作 我们之前都用Controller管理为什么现在用Component 因为Controller就是用Component来实现的。
1.3解耦
1.3.1使用Ioc方法后 传统方法耦合性高我们为了提高代码编写效率就引入了Ioc可以将代码进行解耦操作提高代码编写的效率
1.2中我们只为了更改轮胎的尺寸但是我们改了轮胎Tire之后导致我们还要修改底盘Bottom车身Framework以及汽车Car那么有没有什么方法可以只修改轮胎Tire一个代码呢
传统方法 使用了Ioc之后的方法 通过上述两个图的对比我们可以明显发现使用完Ioc之后无论我们在车上加任意种新的元素我们代码都不会产生关联报错。
使用Ioc的车代码
Car.java: Framwork.java: Bottom.java: Tire.java: Main.java: 运行结果 1.3.2添加变量颜色 只需要修改Tire即可
在Tire中增加color变量 在传参时多传一个颜色参数即可 运行结果 1.4Bean的存储
共有两种注解类型可以实现:
1.注解: Controller、 Service、 Repository、 Component、 Configuration
2.方法注解: Bean.
1.4.1Controller(控制器存储)
启动类和我们的容器类一定要同级或者启动类高于其他类这样启动类中的bean才能拿到其他类中的值 启动类 spring上下文 使用getBean获取spring容器中的对象 可以看到此时我们使用bean来获取spring容器中的值已经成功 如果删除Controller注解就会报如下错误 1.4.2Service(服务存储)
1.4.2.1根据context来获取bean
再写一个userService类我们还是在启动类中使用bean来获取spring容器中的类中的元素 输出结果 注启动类在文件夹中的存放位置一定要等于或高于其他类的位置不然启动类的作用会失效。 1.4.2.2根据名称来获取bean 1.4.2.3根据名称和类型获取bean 1.4.2.4特殊情况-类名前两位都大写bean的名称为类名 1.4.3Repository (仓库存储)
代码 运行结果图 1.4.4Component (组件存储)
代码 运行结果 1.4.5Configuration (配置存储)
代码 运行结果 1.4.6为什么要这么多类注解 - 五大注解
Controller: 控制层接收请求对请求进行处理并进行响应Servie: 业务逻辑层处理具体的业务逻辑Repository: 数据访问层也称为持久层。负责数据访问操作Configuration: 配置层处理项目中的一些配置信息 程序的应用分层调用流程如下 1.4.7Controller和其他注解的区别
使用Controller 可正常访问
使用Service 不能正常返回
证明Controller可以作为程序的入口实现而其他注解不行
1.4.8Bean 使用
1.4.8.1Bean正常使用举例 UserInfo.java: BeanConfig.java: 启动类代码 此时代码没有正常运行产生报错信息 修改代码将根据context获取bean变为根据名称来获取bean 此时程序正常输出结果 总结 可以使用 名称获取bean 或者 根据名称和类型来获取bean 这两种方式都可以成功获取到bean。
1.4.8.2测试Bean传递参数是如何选择的
当name和name2都存在时Bean会取走对应的name值 zhangsan。(与name和name2先后顺序无关) 当name被注释掉只剩name2存在时Bean会取走的name2值 wangwu。(bean会只能取走相关的值而不会不取值除非没有相关定义的name) 结论如果需要的Bean的类型对应的对象只有一个时就直接赋值如果有多个时通过名称去匹配
1.4.9启动类位置关系影响
SpringBoot 特点;约定大于配置
其中之一体现: 就是扫描路径 默认扫描路径是: 启动类所在的目录及其子孙目录 1.5 Bean命名 如何修改BeanName 五大注解 1.6Bean取
1.属性注入 AutoWired
2.构造方法注入
如果只有一个构造方法, AutoWired可以省略
如果有多个构造方法必须使用Qualifier指定(参考2.5.3)一个对象或使用Primary注解标识默认的对象(参考2.5.2)
3.Setter方法注入
Autowired出现的问题 - 参考2.5
2.DI - 依赖注入 2.1属性注入
2.1.1属性注入流程
代码 运行结果图 2.1.2属性注入问题
启动类 UserController.java: BeanConfig.java: 运行结果 当我们使用类UserInfo属性来定义一个新的值时程序没有发生报错一切成功运行
我们修改一下代码将userInfo改为user再次运行 我们可以看到报错了报错信息为我们命名为user后idea找到了一个userInfo和一个userInfo2此时idea不知道应该使用哪一个导致报错 如果只有一个对象属性注入以类型进行匹配与注入的属性名称无关
但是如果一个类型存在多个对象时,优先名称匹配,如果名称 都匹配不上,那就报错~ 2.2构造方法注入
2.2.1只存在一个构造函数时
代码 运行结果图 2.2.2存在多个构造函数时
我们增加一个值后相应的增加了构造函数 此时我们运行报了空指针异常。 通过分析上述代码得知我们idea默认调用了第一个无参的构造函数导致us空指针异常
我们将无参的构造函数注解掉再次运行 报错信息大致为无参构造函数注解掉后idea不知道该使用哪个构造函数导致找不到构造函数从而报错 再次修改代码加上Autowired表示我们给idea指定了要用哪个构造函数再次运行 此时可以发现我们程序运行又回归正常了 总结如果存在多个构造函数时需要加上AutoWired注明使用哪个构造函数。 如果只有一个构造函数时AutoWired可以省略掉 2.3Setter方法注入
当我们直接使用构造函数里面的Setter方法自动生成此时我们的UserService有没有注入进来呢 我们运行一下发现报错了 报错信息为us空指针异常
我们修改一下代码在Setter方法上面加上Autowired 再次运行可以看到我们的元素再次注入成功 从上代码结果可以看出我们在使用Setter方法注入时也需要在Setter方法上加上 Autowired 才能运行成功
2.4三种注入优缺点分析 属性注入 优点简洁使用方便。缺点 只能用于 IoC 容器如果是非 oC 容器不可用并且只有在使用的时候才会出现 NPE(空指针异常)不能注入一个Final修饰的属性 构造函数注入(Spring 4.X推荐) 优点 可以注入final修饰的属性注入的对象不会被修改依赖对象在使用前一定会被完全初始化因为依赖是在类的构造方法中执行的而构造方法是在类加载阶段就会执行的方法通用性好构造方法是JDK支持的所以更换任何框架,他都是适用的 缺点注入多个对象时代码会比较繁琐 Setter注入(Spring 3.X推荐) 优点方便在类实例之后重新对该对象进行配置或者注入缺点 不能注入一个Final修饰的属性注入对象可能会被改变因为setter方法可能会被多次调用就有被修改的风险
2.5Autowired存在问题
当程序中同一个类型有多个对象是使用Autowired会报错(一些情况下)
2.5.1.属性名和你需要使用的对象名保持一致 可以看到只要名称保持一致idea就可以正常找到对应的属性名从而打印出正确的结果。
2.5.2.使用Primary注解标识默认的对象 2.5.3.使用Qualifier idea运行结果 可以看到在加上 Qualifier(userInfo2) 指定属性名后idea在运行时就能按照加的属性名指定使用而不会导致idea不知道使用useInfo还是userInfo2。
2.5.4 使用 Resource 注解 可以看到在我们加上了 Resource 并 Resource(name userInfo2) 指定属性名为 userInfo2 后我们idea也可以正常打印出结果
2.6常见面试题 - Autowird 与 Resouce的区别
Autowired 是spring框架提供的注解而Resource是JDK提供的注解**Autowired 默认是按照类型注入而Resource是按照名称注入.**相比于 Autowired 来说Resource 支持更多的参数设置例如 name 设置根据名称获取 Bean。 一个类型存在多个对象 按照名称来匹配 3.Ioc、DI、AOP的关系
di依赖注入 AOP面向切片 IOC控制反转 spring是一个轻量级控制反转Ioc和面向切片Aop的容器 控制反转IOC是一种设计思想DI依赖注入是实现IOC的一种方法
性名为 userInfo2 后我们idea也可以正常打印出结果
2.6常见面试题 - Autowird 与 Resouce的区别
Autowired 是spring框架提供的注解而Resource是JDK提供的注解**Autowired 默认是按照类型注入而Resource是按照名称注入.**相比于 Autowired 来说Resource 支持更多的参数设置例如 name 设置根据名称获取 Bean。
[外链图片转存中…(img-M4s0g0ws-1712818818828)]
一个类型存在多个对象 按照名称来匹配 3.Ioc、DI、AOP的关系
di依赖注入 AOP面向切片 IOC控制反转 spring是一个轻量级控制反转Ioc和面向切片Aop的容器 控制反转IOC是一种设计思想DI依赖注入是实现IOC的一种方法
感谢各位读者的阅读本文章有任何错误都可以在评论区发表你们的意见我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞你的每一次鼓励都是作者创作的动力哦