Spring初学笔记(一):Spring IOC的理解
关于依赖注入、控制反转
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
在我看来,这句话已经很好的体现了出来IOC思想在编程中的体现形式,而采用这样的思想,可以大大降低类与类之间的耦合度,便于代码的扩展。
这里,我们看一个简单的例子:
我们假设有人和车,他们的类分别如此:
public interface Car {
public void run();
}
public interface Person {
public void Travel();
}
首先定义两个接口,表示要实现的车的功能和人的功能,而在实现人的功能时,旅游总不能光着脚出去吧,假设我们需要一辆车才能出行:
public class BenzCar implements Car{
@Override
public void run() {
System.out.println("奔驰车在跑");
}
}
public class Man implements Person {
private Car car;
public Man(){
car = new BenzCar();
}
@Override
public void Travel() {
System.out.println("我有车了");
car.run();
}
}
这是对应实现好的人类和车类,其中人类依赖于车类,他现在要自己创建一个车的对象,才能实现对应的功能。
我们测试一下这个代码可不可以运行:
public class Test {
public static void main(String[] args) {
Person person = new Man();
person.Travel();
}
}
执行以后,代码可以正常运行,但现在有一个问题,如果这个人过几天有钱了,不想用奔驰了,想换车,那怎么办呢。现在的代码,有一个很明显的问题,就是人和车类的耦合度太高,其原因就是在Man类的内部,自己创造了对应车类的对象,这就导致如果要想修改,只能对Man类的源码进行修改,这也就不符合“对修改关闭,对扩展开放”的原则了。
对这个问题的解决办法就是:不要从内部创建对象,而是由外部传入对象,你只要接收就可以了。
在更改后的代码为:
public class Man implements Person {
private Car car;
public Man(Car car){
this.car = car;
}
@Override
public void Travel() {
System.out.println("我有车了");
car.run();
}
}
将对应的Car类对象的生成方法,由自己new出来,变成通过构造参数传入(当然传入的方法不止一种,像set之类的方法也是可以的,这里只以构造方法为例)
现在对于Man类的扩展问题,我们已经解决了,就算他换成什么车,我们都可以直接在main函数中创建对应的对象,然后直接传入即可。
做到这里,像我这样从来没有大型编程经验的人就觉得已经很好了呀,我不用修改源代码,只要自己在主函数中创建对象,通过我设定的构造器呀set呀等方法传入就可以让程序正常运行啦。
但有多年开发经验的程序员们觉得还不大行,确实这样可以满足了代码复用和开闭原则,但你这样做有一个前提条件,就是你自己熟悉自己所写的全部类,可以明确他们的关系,才能够创建出对应的实体类,但如果是多人开发呢,如果一个人只负责一个模块,那会发生什么样的情况。
从上面我们可以看到,创建一个人的对象,我们需要显式地注入Car的对象,我们很清楚这一点,所以我们可以创造出man类的对象,但如果是多人合作,比如我是写service层的人员,我想调用person的travel()接口,但发现没有实体类,我需要构建。我new一个实体类,结果编译器报错误,我找了半天没找出来哪里有错,最后对Dao管理的人给我说,这个你要传进去一个Car类的对象,其中Car类对象有.xxx,sss之类。
我只是需要调用对象的接口,但这样的注入方法,让我必须清楚对象是如何创建的,而且还要为这个构建去new一个Car对象,这些都是完全不应该由我这样一个写service层的人来做的工作,为了解决这个问题,我们可以采用工厂模式。
先创建一个单例的工厂:
public class Factory {
private Factory() {
}
public static Factory getInstance() {
return inner.instance;
}
private static class inner {
private static final Factory instance = new Factory();
}
}
在工厂中,我们可以创建Man对象:
public Person getMan(){
return new Man(new BenzCar());
}
这样,我们在外部调用的时候,只需要获得工厂,然后通过工厂的方法得到所需对象了,不再需要关心对象到底是如何生成的了。
public static void main(String[] args) {
Factory factory = Factory.getInstance();
Person person = factory.getMan();
person.Travel();
}
原本是调用者直接创建对象,现在改成了通过工厂这个容器,来直接获取对象。
这样,通过工厂方式+注入对象的方法,我们实现了类与类之间的解耦,也完成了生产时调用者只需使用类,而不用关心创建类的功能。
下一篇,我们了解一下在Spring中,对象是如何注入的。
Spring初学笔记(一):Spring IOC的理解的更多相关文章
- Spring 初学笔记
Spring 初学笔记: https://blog.csdn.net/weixin_35909255/article/category/7470388
- Spring初学笔记(二):Bean的注入
关于Bean的注入 在上一篇中,已经说到虽然注入确实可以降低类与类之间的耦合,但并没有解决调用者必须知道类的创建方法的问题,也可以说是没有实现调用者与类实现的解耦,我们也提到,为了实现两者的解耦,可以 ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- Java架构师之路 Spring学习笔记(一) Spring介绍
前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...
- Spring 学习笔记(2) Spring Bean
一.IoC 容器 IoC 容器是 Spring 的核心,Spring 通过 IoC 容器来管理对象的实例化和初始化(这些对象就是 Spring Bean),以及对象从创建到销毁的整个生命周期.也就是管 ...
- Spring 读书笔记-----使用Spring容器(一)
pring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口.他们都可代表Spring容器,Spri ...
- (转)Spring 读书笔记-----使用Spring容器(一)
Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口.他们都可代表Spring容器,Spr ...
- Spring学习笔记--环境搭建和初步理解IOC
Spring框架是一个轻量级的框架,不依赖容器就能够运行,像重量级的框架EJB框架就必须运行在JBoss等支持EJB的容器中,核心思想是IOC,AOP,Spring能够协同Struts,hiberna ...
- Spring Boot笔记十:IOC控制反转
目录 IOC控制反转和DI依赖注入 IOC实现Hello World Spring IOC容器怎么知道哪些是管理的对象? IOC容器getBean方法的三种签名 xml配置文件的import导入 @A ...
随机推荐
- python学习笔记(三)---字典
字典 在Python中,字典 字典 是一系列键 键-值对 值对 .每个键 键 都与一个值相关联,你可以使用键来访问与之相关联的值.与键相关联的值可以是数字.字符串.列表乃至字典.事实上,可将 任何Py ...
- thinkphp5--model数据操作的坑
最近用thinkphp5开发,经常用到model了来操作数据,但是操作多了,就发现他的坑了. 就好像如果你只是初始化一个model对象,但是你却用这个对象进行多次的数据操作,这时候他的数据就会发生混乱 ...
- Windows 挂起进程
A thread can suspend and resume the execution of another thread. While a thread is suspended, it is ...
- Python 如何写 Ubuntu syslog
address='/dev/log' 是关键 import logging from logging.handlers import SysLogHandler logger = logging.ge ...
- 关于CompletableFuture的一切,看这篇文章就够了
文章目录 CompletableFuture作为Future使用 异步执行code 组合Futures thenApply() 和 thenCompose()的区别 并行执行任务 异常处理 java中 ...
- 【Linux常见命令】sort命令
sort - sort lines of text files sort命令用于将文本文件内容加以排序. sort可针对文本文件的内容,以行为单位来排序. 语法: sort [OPTION]... [ ...
- 听说你在从事前端开发?那这10个JavaScript的优化问题你不得不知道!
JavaScript的高效优化一直都是我们前端开发中非常重要的工作,也是很多开发人员无法做好的一部分内容,今天我总结了10个优化问题,大家可以参考来做优化,这其中很多问题都是大家经常遇到的哦. ==和 ...
- 由JS数组去重说起
一.问题描述: var array=[1,45,3,1,4,67,45],请编写一个函数reDup来去掉其中的重复项,即 reDup(array); console.log(array);//[1,4 ...
- Airtest常见的素定位不到
一.为什么发这博客 前几天业务需要需要操作云手机进行爬取没办法只有混进airtest官方群边学习边进行开发,蛮简单的东西(可能是我之前会selenium,appuim关系吧),但是群里会有很多问题,关 ...
- P5522 [yLOI2019] 棠梨煎雪
updata on 2020.3.19 今天把博客从洛谷往博客园搬,图炸了 其实早就发现了,懒得管 那图其实就是一个用dev自带的调试功能调试时,RE了的报错 当时觉得很奇怪看不出是啥,现在再看已经觉 ...