java简单例⼦介绍IOC和AOP
IOC和AOP的⼀些基本概念
介绍 IOC
⼀、什么是IOC
IoC就是Inversion of Control,控制反转。在Java开发中,IoC意味着将你设计好的类交给系统去控制,⽽不是在你的类内部控制。这称为控制反转。
下⾯我们以⼏个例⼦来说明什么是IoC
假设我们要设计⼀个Girl和⼀个Boy类,其中Girl有kiss⽅法,即Girl想要Kiss⼀个Boy。那么,我们的问题是,Girl如何能够认识这个Boy?
在我们中国,常见的MM与GG的认识⽅式有以下⼏种
1 青梅⽵马;2 亲友介绍;3 ⽗母包办
那么哪⼀种才是最好呢?
青梅⽵马:Girl从⼩就知道⾃⼰的Boy。
public class Girl {
void kiss(){
Boy boy = new Boy();
}
}
然⽽从开始就创建的Boy缺点就是⽆法在更换。并且要负责Boy的整个⽣命周期。如果我们的Girl想要换⼀个怎么办?(笔者严重不⽀持Girl 经常更换Boy)
亲友介绍:由中间⼈负责提供Boy来见⾯
public class Girl {
void kiss(){
Boy boy = ateBoy();
}
}
亲友介绍,固然是好。如果不满意,尽管另外换⼀个好了。但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,⽆处不在,⽆处不能。实在是太繁琐了⼀点,不够灵活。我为什么⼀定要这个亲友掺和进来呢?为什么⼀定要付给她介绍费呢?万⼀最好的朋友爱上了我的男朋友呢?
⽗母包办:⼀切交给⽗母,⾃⼰不⽤费吹灰之⼒,只需要等着Kiss就好了。
public class Girl {
void kiss(Boy boy){
// kiss boy
boy.kiss();
}
}
Well,这是对Girl最好的⽅法,只要想办法贿赂了Girl的⽗母,并把Boy交给他。那么我们就可以轻松的和Girl来Kiss了。看来⼏千年传统的⽗母之命还真是有⽤哦。⾄少Boy和Girl不⽤⾃⼰瞎忙乎了。
这就是IOC,将对象的创建和获取提取到外部。由外部容器提供需要的组件。
我们知道好莱坞原则:“Do not call us, we will call you.” 意思就是,You, girlie, do not call the boy. We will feed you a boy。
我们还应该知道依赖倒转原则即 Dependence Inversion Princinple,DIP。
Eric Gamma说,要⾯向抽象编程。⾯向接⼝编程是⾯向对象的核⼼。
组件应该分为两部分,即
Service, 所提供功能的声明
Implementation, Service的实现
好处是:多实现可以任意切换,防⽌ “everything depends on everything” 问题.即具体依赖于具体。
所以,我们的Boy应该是实现Kissable接⼝。这样⼀旦Girl不想kiss可恶的Boy的话,还可以kiss可爱的kit
ten和慈祥的grandmother。⼆、IOC的type
IOC 的Type指的是Girl得到Boy的⼏种不同⽅式。我们逐⼀来说明。
IOC type 0:不⽤IOC
public class Girl implements Servicable {
private Kissable kissable;
public Girl() {
kissable = new Boy();
}
public void kissYourKissable() {
kissable.kiss();
}
}
Girl⾃⼰建⽴⾃⼰的Boy,很难更换,很难共享给别⼈,只能单独使⽤,并负责完全的⽣命周期。
IOC type 1,先看代码:
public class Girl implements Servicable {
Kissable kissable;
public void service(ServiceManager mgr) {
kissable = (Kissable) mgr.lookup(“kissable”);
}
public void kissYourKissable() {
kissable.kiss();
}
}
这种情况出现于Avalon Framework。⼀个组件实现了Servicable接⼝,就必须实现service⽅法,并传⼊⼀个ServiceManager。其中会含有需要的其它组件。只需要在service⽅法中初始化需要的Boy。
另外,J2EE中从Context取得对象也属于type 1。
它依赖于配置⽂件
<container>
<component name=“kissable“ class=“Boy">
<configuration> … </configuration>
</component>
<component name=“girl" class=“Girl" />
</container>
IOC type 2:
public class Girl {
private Kissable kissable;
public void setKissable(Kissable kissable) {
this.kissable = kissable;
public void kissYourKissable() {
kissable.kiss();
}
}
Type 2出现于Spring Framework,是通过JavaBean的set⽅法来将需要的Boy传递给Girl。它必须依赖于配置⽂件。  <bean id=“boy" class=“Boy"/>
<bean id=“girl“ class=“Girl">
<property name=“kissable">
<ref bean=“boy"/>
</property>
</bean>
IOC type 3
public class Girl {
private Kissable kissable;
public Girl(Kissable kissable) {
this.kissable = kissable;
}
public void kissYourKissable() {
kissable.kiss();
}
}
这就是PicoContainer的组件。通过构造函数传递Boy给Girl。
PicoContainer container = new DefaultPicoContainer();
Girl girl = (Girl) ComponentInstance(Girl.class);
girl.kissYourKissable();
================
AOP 关注与主要的东西,也可以说让你只关注与业务,其他的东西就让AOP帮你完成。
我们要吃武昌鱼:
public class Dinner {
Customer yangyi;
public void eatfish() {
yangyi.eatFish();
yangyi.washDish();
}
}
prog 1
现在我觉得这顿饭吃的太不爽了,还要⾃⼰做,洗碗。
我想这样
public class Dinner {
ICustomer yangyi;
public void eatfish() {
yangyi.eatFish();
}
}
就是说我现在只⽤吃就⾏了,但是这样可以么?
谁来帮我做鱼呢?这个我想就是所谓AOP吧,我只⽤关⼼我吃鱼的⽅⾯就⾏了,做鱼⼜⾷堂关注就⾏了。
现在看看谁来帮我cook fish呢,它怎么做到的呢?
我看到上⾯prog 1中的Customer已经变成了prog 2中的ICustomer了,就是说如果愿意,我可以⽤任意的ICustomer实现来替代yangyi了,这个就是⼀个Customer的代理,在调⽤ yangyi.eatfish的时候,之前
代理会帮我调⽤cookfish(),之后代理会帮我调⽤washdish()
还是看看代码吧
class Customer implements ICustomer {
void eatfish() {
//haha eat, delicious
}
}
class CustomerProxy implements ICustomer {
Customer yangyi = new Customer() //just for example. proxy is implement by dynamic proxy or other tech in real world
void eatfish() {
cookfish();
yangyi.eatfish();
washdish();
}
}
基本上就是说proxy会在调⽤我的Customer代码之前和之后做⼀些⼯作,ok, 这就是AOP,不知道我讲清楚了没有。在spring中,proxy是⽤java的动态代理做的,在运⾏的时候⾃动⽣成CustomerProxy这个东西,然后⽤这个Proxy替代我的Customer。
为什么⽼把IOC和AOP放在⼀起讲呢,想想我们的Customer是怎么来的吧
如果在某个时候我们说yangyi = new Customer(),那这样Proxy怎么替代这个Customer啊。
所以IoC说,你要⽤Customer么,你直接说我要⽤,声明他,告诉我怎么样能够设置这个Customer,⽤的时候我会来调⽤你的(don't call me, but I call you)
所以真正的代码应该是这样的
public class Dinner {
ICustomer yangyi;
public void eatfish() {
yangyi.eatFish();
}
public void setYangyi(ICustomer customer) {
this.yangyi = customer;
}
}
我提供⼀个SetYangyi的⽅法,IoC会在运⾏时把yangyi设置成CustomerProxy,然后,我的代码就只⽤尽情的享受武昌鱼的美味了。其它的,留给ioc了。
BTW,烦死JDBC的connection.close()了吧,呵呵,IOC+AOP应该最适合这⽅⾯了。
这两个概念基本上是⼀个设计层的概念,主要讲的就是怎么去分离关注,⽤⾯向对象的话说,就是怎么把职责进⾏分离。⽽这两个模式,我个⼈认为都有⼀个共同点,就是变以前的主动为被动,⽽我认为,这种改变可能也是将来⾯向对象发展的⼀个趋势。
⾸先说说什么叫主动。写过⾯向对象程序的⼈都知道,⾯向对象与⾯向过程的区别就是,⾯向对象是由⼀⼤堆对象组成的,对象通过协作完成⾯向过程中的任务。假设现在有对象A和B,那么当A需要使⽤B中的⽅法时,那么在A内部,就会有有⼀个对B⽅法的调⽤,这种调⽤就称为主动调⽤。代码⼤概会如下:
java做什么的
public class A{
B b;
public void methodA(){
}
}
这⾥为了下⽂解释⽅便,我增加了⼀个调⽤点的定义,调⽤点就是调⽤发⽣的地⽅。也就是上⾯
理解了什么叫主动之后,我想就先介绍什么叫IoC。IoC的全称这⾥就不说了,他的字⾯意思就是控制反转。在上⾯的代码当中,由于A调⽤了B的⽅法,因此就形成了⼀个A对B的依赖,这本⾝并没有什么问题。但是OO的思想是希望我们基于接⼝编程,⽽不是基于实现编程。因此,系统设计将不⽌是原有的A,B,⽽需要变成IA,IB,A,B,其中IA,IB是接⼝,A,B是对应的实现类,然后为了使得A中现在对B的实现依赖变成对接⼝的依赖,代码应该变成这样。
public class A implements IA{
IB b;
public void methodA(){
}
}
这⾥虽然我们是基于接⼝编程了,但⼤家知道,在这中间,我们需要有⼀个步骤把b指向⼀个IB的实现类B,这个怎么做,就是IoC要做的事情,这⾥就不细说了。但简单来说,没有IoC,我们可能需要在A中通过某种⽅法去获取⼀个B的实例,但有了IoC,她就能在A不参与的情况下,给我们⼀个B的实例,所以,IoC要做的就是在调⽤点上从原来的主动⽣成⼀个调⽤点,变成被动的接受⼀个调⽤点。
接着就是AOP,全称也不说了,字⾯意思就是⾯向⽅⾯编程。举⼀个最普遍的例⼦,就是如果我们代码需要做⽇志的话,那么在没有AOP的时候,我们的代码可能就是这样:
public class A{
public void methodA(){
do log;
}
}
这⾥methodA()中的做⽇志并不是⽅法本⾝的逻辑功能,⽽是⼀个附属功能,因此,我们需要把它分离出去。怎么分离,就是AOP要做的事情,简单来说,就是系统在调⽤者不知情的情况下,为我们的类A增加了⼀个代理类,她把我们的类A包装了起来,像这样:
public class AP extends A{
A a;
public void methodA(){
do log;
}
}
public class A{
public void methodA(){
}
}
于是,当我们以为⾃⼰在调⽤A的methodA()⽅法时,实际调⽤的将是AP中的methodA(),于是就可以把做⽇志的功能从原有的methodA()中分离了出去。所以,AOP要做的就是在⽤户不知道的情况下,将我们的调⽤点包裹了起来,从⽽把原来的功能进⾏了分离。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。