forked from hellokaton/java-bible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
crane-yuan
committed
Sep 1, 2017
1 parent
3ea0c93
commit 26483e0
Showing
99 changed files
with
52,631 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
1,318 changes: 1,318 additions & 0 deletions
1,318
_book/articles/electrical-business-architecture.html
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
1,151 changes: 1,151 additions & 0 deletions
1,151
_book/articles/software_architecture_patterns.html
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# IOC的概念 | ||
|
||
## 什么是IOC? | ||
|
||
IoC(Inversion of Control),意为控制反转,不是什么技术,而是一种设计思想。Ioc意味着**将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制**。 | ||
|
||
如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下: | ||
|
||
- **谁控制谁,控制什么**:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。 | ||
|
||
- **为何是反转,哪些方面反转了**:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。 | ||
|
||
下面举个例子说明说明是IOC: | ||
|
||
假设我们要设计一个Girl和一个Boy类,其中Girl有kiss方法,即Girl想要Kiss一个Boy。那么,我们的问题是,Girl如何能够认识这个Boy? | ||
|
||
在我们中国,常见的MM与GG的认识方式有以下几种: | ||
|
||
|
||
1. 青梅竹马 | ||
2. 亲友介绍 | ||
3. 父母包办 | ||
|
||
那么哪一种才是最好呢? | ||
|
||
1. **青梅竹马:Girl从小就知道自己的Boy。** | ||
|
||
```java | ||
public class Girl { | ||
void kiss(){ | ||
Boy boy = new Boy(); | ||
} | ||
} | ||
``` | ||
|
||
然而从开始就创建的Boy缺点就是无法在更换。并且要负责Boy的整个生命周期。如果我们的Girl想要换一个怎么办?(笔者严重不支持Girl经常更换Boy) | ||
|
||
2. **亲友介绍:由中间人负责提供Boy来见面** | ||
|
||
```java | ||
public class Girl { | ||
void kiss(){ | ||
Boy boy = BoyFactory.createBoy(); | ||
} | ||
} | ||
``` | ||
|
||
亲友介绍,固然是好。如果不满意,尽管另外换一个好了。但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,无处不在,无处不能。实在是太繁琐了一点,不够灵活。我为什么一定要这个亲友掺和进来呢?为什么一定要付给她介绍费呢?万一最好的朋友爱上了我的男朋友呢? | ||
|
||
3. **父母包办:一切交给父母,自己不用费吹灰之力,只需要等着Kiss就好了。** | ||
|
||
```java | ||
public class Girl { | ||
void kiss(Boy boy){ | ||
// kiss boy | ||
boy.kiss(); | ||
} | ||
} | ||
``` | ||
|
||
Well,这是对Girl最好的方法,只要想办法贿赂了Girl的父母,并把Boy交给他。那么我们就可以轻松的和Girl来Kiss了。看来几千年传统的父母之命还真是有用哦。至少Boy和Girl不用自己瞎忙乎了。 | ||
|
||
这就是IOC,将对象的创建和获取提取到外部。由外部容器提供需要的组件。 | ||
|
||
## IoC能做什么 | ||
|
||
IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。 | ||
|
||
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。 | ||
|
||
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。 | ||
|
||
## IoC和DI | ||
|
||
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。 | ||
|
||
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下: | ||
|
||
- 谁依赖于谁:当然是应用程序依赖于IoC容器; | ||
|
||
- 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源; | ||
|
||
- 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象; | ||
|
||
- 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。 | ||
|
||
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。 | ||
|
||
对于Spring Ioc这个核心概念,我相信每一个学习Spring的人都会有自己的理解。这种概念上的理解没有绝对的标准答案,仁者见仁智者见智。 | ||
理解了IoC和DI的概念后,一切都将变得简单明了,剩下的工作只是在框架中堆积木而已,下一节来看看Spring是怎么用的 | ||
|
||
## links | ||
* [目录](<index.md>) | ||
* 下一节: [Spring中怎么用](<2.spring.md>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Spring中怎么用 | ||
|
||
我们在Spring中是这样获取对象的: | ||
|
||
```java | ||
public static void main(String[] args) { | ||
ApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml"); | ||
Lol lol = (Lol) context.getBean("lol"); | ||
lol.gank(); | ||
} | ||
``` | ||
|
||
一起看看Spring如何让它生效呢,在 `applicationContext.xml` 配置文件中是酱紫的: | ||
|
||
```xml | ||
<bean id="lol" class="com.biezhi.test.Lol"> | ||
<property name="name" value="剑圣" /> | ||
</bean> | ||
``` | ||
|
||
`Person` 类是这样的: | ||
|
||
```java | ||
public class Lol { | ||
|
||
private String name; | ||
|
||
public Lol() { | ||
} | ||
|
||
public void gank(){ | ||
System.out.println(this.name + "在gank!!"); | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
} | ||
``` | ||
|
||
上面的代码运行结果自然是 `剑圣在gank!!`。 | ||
|
||
Spring更高级的用法,在3.0版本之后有了基于Annotation的注入实现,为毛每次都要配置 `Xml` 看到都蛋疼。。 | ||
|
||
首先还是要在 `xml` 中配置启用注解方式 | ||
|
||
```xml | ||
<context:annotation-config/> | ||
``` | ||
|
||
这样就能使用注解驱动依赖注入了,下面是一个使用场景 | ||
|
||
```java | ||
public class Lol { | ||
|
||
@Autowired | ||
private DuangService duangService ; | ||
|
||
public void buyDuang(String name, int money) { | ||
duangService.buy(name, money); | ||
} | ||
} | ||
``` | ||
|
||
```java | ||
@Service("duangService") | ||
public class DuangService { | ||
|
||
public void buy(String name, int money){ | ||
if(money > 0){ | ||
System.out.println(name + "买了" + money + "毛钱的特效,装逼成功!"); | ||
} else{ | ||
System.out.println(name + "没钱还想装逼,真是匪夷所思"); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
这只是一个简单的例子,剑圣打野的时候想要买5毛钱的三杀特效,嗯。。虽然不符合逻辑 | ||
|
||
此时 `DuangService` 已经注入到 `Lol` 对象中,运行代码的结果(这里是例子,代码不能运行的)就是: | ||
|
||
```sh | ||
德玛买了5毛钱的特效,装逼成功! | ||
``` | ||
|
||
好了,深入的不说了,我们不是学spring的,只是知道一下ioc在spring中高大上的形象,接下来步入正轨,开始设计一个IOC容器 | ||
|
||
## links | ||
* [目录](<index.md>) | ||
* 上一节: [IOC的概念](<1.concept.md>) | ||
* 下一节: [设计一个IOC](<3.myioc.md>) |
Oops, something went wrong.