首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Spring温故知新(6)AOP面向切面编程 <1>

2012-12-22 
Spring温故知新(六)AOP面向切面编程 1这一章我们将开始剖析Spring框架最为重要的AOP(Aspect Oriented Pr

Spring温故知新(六)AOP面向切面编程 <1>
这一章我们将开始剖析Spring框架最为重要的AOP(Aspect Oriented Programming)面向切面编程。可以说Spring的精华就在于AOP了。
所谓AOP,就是相对于OOP(Object Oriented Programming)面向对象编程的说法,有些人喜欢叫面向切面编程,有些人喜欢叫做面向方面,事实上这两个都是指同一个东西,只是叫法不同。
我们传统的编程都是面向对象,就是说每个类都有它实际的意义。而面向切面略有不同,它在面向对象的基础上扩展了一下,它编程的时候不是先考虑的一个具体对象(比如用户类),而是先考虑的对象的行为或者功能。这个不是编程方法的不同,而是编程思维的转变。

理论性的东西还是放一边,我们用实际的机器人案例来慢慢理解这个概念。
为了突出重点我们这里重写了ISpeak:

package com.iteye.bolide74.impl;public interface ISpeaker {public void say(String msg);}

接着是实现这个接口的机器人类:
package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;public class Robot implements ISpeaker {public String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public Robot(String name) {this.name = name;}@Overridepublic void say(String msg) {System.out.println("到达邻居家,对邻居说:" + msg + ",我是" + this.name);}}

那么现在我们要实现跟很多个不同的邻居(不同的应用代码)打招呼,只需要下面的应用代码了:
package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Robot;import com.iteye.bolide74.impl.ISpeaker;public class Tester {public static void main(String[] args) {ISpeaker speaker = new Robot("Wall-E");speaker.say("你好");}}


以上是实现最简单功能的方法。现在我们要慢慢增加功能了,假设Wall-E在出发打招呼之前要先拿一个礼物,然后打完招呼以后把礼物递给邻居,该怎么实现呢?
public void getGift() {System.out.println("获取了一个礼物");}public void giveGift(){System.out.println("赠予一个礼物");}


最傻的办法就是每次在应用代码里调用speaker.say()方法的前后都调用get/give方法,小程序还好,要是大型程序的话人都要写傻掉。
那么能不能直接把get/give方法写在Robot类的say()方法里呢?这样好处是每次调用say()的时候都能实现get/give功能,但是坏处也是这个:万一有个别邻居是不需要给礼物的呢?怎么办?
那有没有更加灵活的办法呢?当然有!

代理模式:
我们先新建一个SpeakerProxy代理类:
package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;public class SpeakerProxy implements ISpeaker {ISpeaker speaker;public SpeakerProxy(ISpeaker speaker) {super();this.speaker = speaker;}@Overridepublic void say(String msg) {getGift();speaker.say(msg);giveGift();}public void getGift() {System.out.println("获取了一个礼物");}public void giveGift(){System.out.println("赠予一个礼物");}}

这个SpeakerProxy类实现了ISpeaker接口,然后又有一个靠构造函数传入的ISpeaker类型的成员属性。
而这个SpeakerProxy类的say()方法就有点意思了,它不是重写了自己的say()方法,而是调用了ISpeaker类型的speaker成员属性的say()方法,然后再这个say()方法前后嵌入get/give方法。
让我们看看这个SpeakerProxy类是怎么在应用代码使用:
package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Robot;import com.iteye.bolide74.action.SpeakerProxy;import com.iteye.bolide74.impl.ISpeaker;public class SpeakerProxyTester {public static void main(String[] arg0) {// 没有带礼物的机器人:ISpeaker noGiftSpeaker = new Robot("空手来的Wall-E");noGiftSpeaker.say("你好");System.out.println();// 带了礼物的机器人ISpeaker speaker = new SpeakerProxy(new Robot("有礼而来的Wall-E"));speaker.say("你好");}}

输出结果:
package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;public abstract class SpeakerGiftDecorator implements ISpeaker {ISpeaker speaker;public SpeakerGiftDecorator(ISpeaker speaker) {super();this.speaker = speaker;}public abstract void say(String msg);public abstract void getGift();public abstract void giveGift();}
这是一个礼物的装饰器类,你可以理解为各种礼物的组装器。它的写法跟代理模式的代理类很像,不同的就是它是一个抽象类。它是所有种类的礼物的父类。
接下来就写一个继承了这个SpeakerGiftDecorator类的礼物之类:
package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;//礼物的一种:一束花public class Flower extends SpeakerGiftDecorator {public Flower(ISpeaker speaker) {super(speaker);}@Overridepublic void say(String msg) {getGift();this.speaker.say(msg);giveGift();}@Overridepublic void getGift() {System.out.println("获取了一束花");}@Overridepublic void giveGift() {System.out.println("赠予一束花");}}

以上面的Flower子类类推来写出另外的Money类和Fruit类,区别仅在于get/give方法的内容不同,这里就不浪费篇幅了。

看起来代码似乎很简单,没什么出奇的,但是当应用代码使用的时候就能体现出它强大的地方了:
package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Flower;import com.iteye.bolide74.action.Fruit;import com.iteye.bolide74.action.Money;import com.iteye.bolide74.action.Robot;import com.iteye.bolide74.impl.ISpeaker;public class SpeakerGiftDecoratorTester {public static void main(String[] args) {// 一种礼物:ISpeaker speaker = new Flower(new Robot("我是带花来的Wall-E"));speaker.say("Hello");System.out.println();// 两种礼物:speaker = new Money(new Flower(new Robot("我是带了花和红包的Wall-E")));speaker.say("Hello");System.out.println();// 另外两种礼物:speaker = new Fruit(new Money(new Robot("我是带了水果和钱的Wall-E")));speaker.say("Hello");System.out.println();// 三种礼物:speaker = new Fruit(new Money(new Flower(new Robot("我是三种礼物都带的Wall-E"))));speaker.say("Hello");}}

可以看到,speaker引用的是一个一层一层嵌套的类,要多带一种礼物那就多嵌套一层,这样就能尽可能的实现了代码的重用,而且应用起来也简单明了。


输出结果:
  不错,这样的例子很有感觉 2 楼 qj200040 2011-04-24   嗯,不错的例子,我要好好学习学习,谢谢你哈 3 楼 chenming47 2011-04-25   不错,讲的通俗易懂

热点排行