曹操自剿黄巾,讨董作,擒吕布,灭袁绍后,队伍达到鼎盛期,拥有兵将100余万,为了统一全国,派手下将领夏候淳领兵十万攻打新野。时当秋月,秋风徐起,夏侯惇引兵至博望坡,新野危在旦夕。

刘备请军师诸葛亮对策。诸葛亮给出的计策是引诱曹军到达博望坡南处后实施火攻。命赵云在北部与曹兵对敌,只输不赢,刘备引本部人马兵援赵云诱敌深入,将曹兵引入峡谷。命关羽领兵1000在博望坡之左玉山右边的安林脚下伏兵,不可动,等曹兵经过看见南面火起出兵围之。命张飞领1000往安林背后山谷埋伏,见南面火起向博望坡存粮处纵火出击。命关平、刘封领500兵马预备引火之物背靠博望坡南处埋伏,曹兵到时放火烧之。

当然,这场战的最后结果是,诸葛亮只用几千兵马在峡谷内火烧夏候淳十万兵马,夏候淳大败而归。


浅析博望坡一役火攻为何可行

曹操发起战争,刘备的决定火拼。诸葛亮想,既然要战,那行,先来个火烧曹军,然后再打。诸葛亮为何想出火烧曹军,并非随便想想而已,这也是有根据的。诸葛亮熟读兵书,而孙子兵法上说:

“凡火攻有五:一曰火人,二曰火积,三曰火辎,四曰火库,五曰火队。行火必有因,烟火必素具。发火有时,起火有日。时者,天之燥也;日者,月在箕、壁、翼、轸也。凡此四宿者,风起之日也。”

这段话就是说:火烧的目标就是敌军人马、粮草辎重、仓库设施。那么火攻的条件就是天气干燥有风以及引火材料。而曹军到达离新野不远的博望坡时,正好满足天气干燥有风的条件,因此火攻是可行的。


Spring AOP实现博望坡一役

纵观博望坡一役,诸葛亮实质上是一个拥有丰富经验的程序员,而孙子兵法是开发大牛孙武编写的一个包含有计策(Advice)和计策运用条件(Pointcut)的一个xml配置文件。在孙子兵法中,火攻篇就是一个Advisor,其中的计策火攻就是一个Advice,实施火攻的条件干燥有风就是一个Pointcut。诸葛亮开发博望坡一役项目时,正因为根据该项目所处具体情况在曹刘双方火拼前(Joinpoint)使用了孙子兵法火攻篇(Advisor),才成功完成了对曹军的截杀,为最后刘备军团获胜提供了条件。下面我们用代码来实现博望坡一役。

(1)定义一个WarCamp 类来表示作战双方阵营,代码如下。

public class WarCamp {//战斗力private float effectiveness = 100;public float getEffectiveness() {return effectiveness;}/*** 添加战斗力* @param effectiveness*/public void addEffectiveness(float effectiveness){this.effectiveness += effectiveness;}
}

(2)定义战争接口

public interface IWar {/*** 打战* @param enemy 敌方阵营* @param myCamp 我方阵营* @return true表示我方阵营赢得胜利,false表示敌方胜利,null表示平手*/Boolean fight(WarCamp enemy, WarCamp myCamp);
}

(3)在com.chyohn.war.dry.wind包中实现战争IWar接口

public class WarAtBoWangPo implements IWar {@Overridepublic Boolean fight(WarCamp enemy, WarCamp myCamp) {System.out.println("作战双方正在火拼");if (myCamp.getEffectiveness() == enemy.getEffectiveness()) {// 平手return null;}// 作战最后比较双方军队实力return myCamp.getEffectiveness() > enemy.getEffectiveness();}
}

(4)配置xml文件spring-aop.xml,定义战争bean

    <!--定义战争Bean--><bean id="war" class="com.chyohn.war.dry.wind.WarAtBoWangPo" />

(5)编写main方法发起博望坡之战

    public static void main(String[] args) throws Exception{ApplicationContext cxa = new ClassPathXmlApplicationContext("classpath:spring-aop.xml");// 曹操阵营,战斗力为100WarCamp caocao = new WarCamp();// 刘备阵营,战斗力为40WarCamp liubei = new WarCamp();liubei.addEffectiveness(-60);// 发起战争IWar war = cxa.getBean(IWar.class);Boolean win = war.fight(caocao, liubei);// 战后结果System.out.println("曹操军战斗力:" + caocao.getEffectiveness());System.out.println("刘备军战斗力:" + liubei.getEffectiveness());if (win == null) {System.out.println("双方平手");} else {String winner = win ? "刘备" : "曹操";System.out.println(winner + "胜");}}

运行结果

作战双方正在火拼
曹操军战斗力:100.0
刘备军战斗力:40.0
曹操胜

这种曹操胜刘备败的结果是因为刘备军团在敌我悬殊非常大的情况下与曹操军团正面交锋造成的。下面我们分别通过Spring的AOP的5种使用方式来引入孙子兵法中的火攻一策来帮助刘备军团获取胜利。

1. 配置ProxyFactoryBean实现通过火攻发起作战

(1)实现火烧敌军的计策(Advice),代码如下。

public class FireCampOfEnemy implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("火烧敌军阵营, 敌军战斗力降低40个点");WarCamp enemy = (WarCamp)args[0];enemy.addEffectiveness(-40);System.out.println("我军阵营战斗力提升低40个点");WarCamp myCamp = (WarCamp)args[1];myCamp.addEffectiveness(40);}
}

(2)重新配置spring-aop.xml文件

       <!--定义Advisor:孙子兵法.火攻篇--><bean id="fireAttachAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property name="advice"><bean class="com.chyohn.aop.service.war.FireCampOfEnemy"/></property><!--定义切点:火攻的条件--><property name="pattern" value=".*war\.dry\.wind.*"/></bean><!--通过ProxyFactoryBean定义战争对象--><bean id="war" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="proxyTargetClass" value="true"/><property name="target"><!--战争对象--><bean class="com.chyohn.aop.service.war.dry.wind.WarAtBoWangPo" /></property><property name="interceptorNames"><array><value>fireAttachAdvisor</value></array></property></bean>

运行main方法后的结果如下:

火烧敌军阵营, 敌军战斗力降低40个点
我军阵营战斗力提升低40个点
作战双方正在火拼
曹操军战斗力:60.0
刘备军战斗力:80.0
刘备胜

2. AOP自动代理实现通过火攻发起作战

修改spring-aop.xml配置

       <!--定义Advisor:孙子兵法.火攻篇--><bean id="fireAttachAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property name="advice"><bean class="com.chyohn.aop.service.war.FireCampOfEnemy"/></property><!--定义切点:火攻的条件--><property name="pattern" value=".*war\.dry\.wind.*"/></bean><!--战争对象--><bean class="com.chyohn.aop.service.war.dry.wind.WarAtBoWangPo" /><!--向容器中添加一个自动代理构造器--><!--这种方式可以自动匹配需要增强的方法和类--><bean class="org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator"/>

运行结果如下:

火烧敌军阵营, 敌军战斗力降低40个点
我军阵营战斗力提升低40个点
作战双方正在火拼
曹操军战斗力:60.0
刘备军战斗力:80.0
刘备胜

3. 使用<aop:config>标签的子标签配置AOP

使用<aop:config>标签有两种方式配置AOP,其一是和前面两种方式一样实现Advice接口并用<aop:advisor>标签实现;其二是定义一个POJO类,并用<aop:aspect>标签的子标签指定增强方法。下面分别介绍这里中。

使用<aop:advisor>实现通过火攻发起作战

使用这种方式有两步,首先实现Advice接口,然后在xml文件中配置Advisor。
这里沿用前面两种方式的Advice,那么这里只需修改spring-aop.xml配置,修改后内容如下。

        <!--战争对象--><bean class="com.chyohn.aop.service.war.dry.wind.WarAtBoWangPo" /><!--定义Advice:火攻--><bean id="fireCampOfEnemy" class="com.chyohn.aop.service.war.FireCampOfEnemy"/><aop:config><!--定义Pointcut:干燥有风--><aop:pointcut id="firePointcut" expression="within(*..war.dry.wind.*)"/><!--定义Advisor:孙子兵法.火攻篇--><aop:advisor advice-ref="fireCampOfEnemy" pointcut-ref="firePointcut"/></aop:config>

运行结果如下

火烧敌军阵营, 敌军战斗力降低40个点
我军阵营战斗力提升低40个点
作战双方正在火拼
曹操军战斗力:60.0
刘备军战斗力:80.0
刘备胜
使用<aop:aspect>标签实现通过火攻发起作战

这种方式也是简单两步:首先自定义一个含有增强逻辑的POJO,然后使用<aop:aspect>标签下的子标签指定增强方法。
(1)自定义POJO指定增强方法。
定义一个POJO类,名称为SunZiBingFa如下。

public class SunZiBingFa {/*** 火攻* @param joinPoint*/public void fire(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();System.out.println("火烧敌军阵营, 敌军战斗力降低40个点");WarCamp enemy = (WarCamp)args[0];enemy.addEffectiveness(-40);System.out.println("我军阵营战斗力提升低40个点");WarCamp myCamp = (WarCamp)args[1];myCamp.addEffectiveness(40);}}

fire方法的内容和FireCampOfEnemy内容差不多。

(2)下面修改spring-aop.xml文件,代码如下。

       <!--战争对象--><bean class="com.chyohn.aop.service.war.dry.wind.WarAtBoWangPo" /><!--孙子兵法--><bean id="sunZiBingFa" class="com.chyohn.aop.service.war.SunZiBingFa"/><aop:config><!--定义Pointcut:干燥有风--><aop:pointcut id="firePointcut" expression="within(*..war.dry.wind.*)"/><!--定义Advisor:孙子兵法.火攻篇--><aop:aspect ref="sunZiBingFa"><aop:before method="fire" pointcut-ref="firePointcut"/></aop:aspect></aop:config>

运行结果如下。

火烧敌军阵营, 敌军战斗力降低40个点
我军阵营战斗力提升低40个点
作战双方正在火拼
曹操军战斗力:60.0
刘备军战斗力:80.0
刘备胜

4. 使用<aop: aspectj-autoproxy>配置实现通过火攻发起作战

这种方式则全基于注解来定义一个AOP,和<aop:config>的第二种方式一样,定义一个POJO类,并在这个类中使用AspectJ的注解。
(1)修改SunZiBingFa 类,代码如下。

@Aspect
public class SunZiBingFa {/*** 火攻* @param joinPoint*/@Before("within(*..war.dry.wind.*)")public void fire(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();System.out.println("火烧敌军阵营, 敌军战斗力降低40个点");WarCamp enemy = (WarCamp)args[0];enemy.addEffectiveness(-40);System.out.println("我军阵营战斗力提升低40个点");WarCamp myCamp = (WarCamp)args[1];myCamp.addEffectiveness(40);}}

(2)修改spring-aop.xml文件,代码如下。

       <!--战争对象--><bean class="com.chyohn.aop.service.war.dry.wind.WarAtBoWangPo" /><!--孙子兵法--><bean id="sunZiBingFa" class="com.chyohn.aop.service.war.SunZiBingFa"/><aop:aspectj-autoproxy/>

运行结果如下。

火烧敌军阵营, 敌军战斗力降低40个点
我军阵营战斗力提升低40个点
作战双方正在火拼
曹操军战斗力:60.0
刘备军战斗力:80.0
刘备胜

总结

(一)使用Spring AOP代理只需要开发者只需做如下3三件事情:
1. 定义和配置增强处理类(Advice或者自定义POJO)。
2. 在配置中定义切点(Pointcut)。
3. 在配置中定义切面 (Advisor)。

(二)5中使用方式代码量从少到多

从诸葛亮博望坡火烧曹军谈Spring AOP 的五种使用方式相关推荐

  1. 谈表达式树的缓存(7):五种缓存方式的总体分析及改进方案

    终于到了这个系列的最后一篇文章了,这个系列的文章本是许多话题的基础,却拖了那么长时间还没有完结.这篇文章主要讨论五种缓存方式各自的优劣,以及他们的性能关键在什么地方,如果要进行改进又有什么可选方案.在 ...

  2. 谈表达式树的缓存(6):五种缓存方式的性能比较

    开始还债,因为还有至少两个可写的重要话题依赖在这个系列上,不解决就难以前进. 目前我们已经涉及了五种不同的缓存实现,它们分别是: SimpleKeyCache:构造字符串作为Key,使用字典作为存储. ...

  3. 浅谈Zebra斑马打印机三种打印方式的利弊

    经过几个项目的洗礼,对Zebra打印机有了一个初步的了解,也用了好几种方式进行通讯打印,下面我们来谈谈这几种方式的优缺点吧. 主要有以下三种方法: 1.利用ZPLII指令集编写带有位置信息,字体大小, ...

  4. 浅谈NAND FLASH的两种编程方式

    NAND Flash 一般有两种编程方式:one shot or two pass. 这里以TLC为例,如图为LUN的结构: 1. 如果以ONE Shot 编程(eg: bisc3), 如图: 如上图 ...

  5. 【第一回】曹操计用优惠券 孔明火烧博望坡

    却说玄德问计于孔明,何为拒曹兵之计.孔明曰:"新野三线小县,不可久居也,日后房价必跌,有损吾军之储也." 翌日,孔明至博望坡,此乃草茂而木裕之地也.孔明大喜,心暗自忖曰:" ...

  6. 爆笑三国之火烧博望坡

    场景:天还没有完全亮,曹军沿山麓向新野进发,连绵不绝. 士兵甲:有没有搞错,一大早就要人起床,我牙还没刷呢! 士兵乙:根据我的观察,我们是要去打仗.这幺多人,军官是不会请我们喝早茶的. 士 ...

  7. 诸葛亮草船借箭时,曹军当初为什么不放火箭?

    诸葛亮草船借箭时,曹操傻傻的被骗走了十万支箭,很多人要问:曹军当初为什么不放火箭?让诸葛亮白捡了这个便宜.以下是各方人士对此事件的看法:   1.大批量使用火箭成本过高,硫磺烟硝在当时是"高 ...

  8. 内外兼修:Oracle ACED熊军谈Oracle学习

    编辑手记:熊军是中国西部第一位,也是到目前为止唯一的Oracle ACE总监,在这篇文章中熊军描述了他的学习过程和理念供大家参考. ORACLE 的学习,就好比武侠小说中学武功.要从三方面入手: 1. ...

  9. 转载:内外兼修:Oracle ACED熊军谈Oracle学习

    内外兼修:Oracle ACED熊军谈Oracle学习 熊军是中国西部第一位,也是到目前为止唯一的Oracle ACE总监,在这篇文章中熊军描述了他的学习过程和理念供大家参考. ORACLE 的学习, ...

最新文章

  1. 13.MapReduce第3部分(编程实践WordCount)
  2. python中time库是什么意思_python中time库的time.time()函数的作用是什么
  3. JavaFX真实世界应用程序:欧洲电视网广播联盟
  4. 【今日CS 视觉论文速览】 18 Dec 2018
  5. 配置Eclipse 实现按任意键代码自动补全
  6. Function(函数)
  7. 使用Anaconda3配置多版本Python虚拟开发环境详细步骤
  8. Do 32-bit build only with XCode 5.1
  9. Mongo 常用的server命令
  10. Java集合Collection之实现原理解读(Map)
  11. html5制作叮当猫,HTML5 canvas画简单的叮当猫头
  12. android电视接跳舞毯,跳舞毯怎么连接电视以及注意事项
  13. 代理服务器搭建socks5环境的方法
  14. 宏基服务器 安装系统,宏基Acer笔记本重装系统win7图文安装教程
  15. java pem 读取_java读取微信Pem格式证书对字段加密
  16. 【UE】BUILD ERROR: Missing precompiled manifest for ‘****‘.
  17. 在没有搜索功能的网站中寻找指定内容
  18. Redis从入门到精通
  19. 宽带拨号上网显示服务器失效,拨号上网失败 宽带连接错误651怎么办
  20. 大数据学习路线,如何学习大数据?

热门文章

  1. 数据挖掘第八章——聚类分析
  2. Meego针对Nokia N900/N950/N9社区版发布
  3. Linux分区和备份操作
  4. 高压功率放大器在脉冲X射线源技术及火星X射线通信中的应用
  5. Redis 性能影响 - 内存碎片和缓冲区
  6. 如何修改element-ui中输入框点击之后的边框高亮
  7. 漫谈程序员:怎样成为技术达人
  8. 用sql语句快速生成大量数据,批量生成数据
  9. 物理学专业英语(写作整理)01
  10. 大脑笔记:古诗词思维导图涂鸦记忆法