DI实现松耦合,AOP实现可重用组件
日志模块、安全模块、事务模块都是单一的模块,只实现了自身功能,左边的各种服务要用到该模块时就要去调用,但是这些模块并不是左边服务的只要业务,却要不停的去调用,比较浪费时间。使用AOP组件化后如下
拿日志来举例子,日志覆盖到了他所影响到的所有的服务,各个服务可以不知道日志的存在。这样说有点说不清楚,举个例子来说吧
还是拿一篇中的骑士举例子,给每个骑士分配一个歌者(相当于日志模块),在骑士开始任务以前,唱歌歌颂(日志记录下),在骑士完成任务后,唱歌歌颂(日志记录下)。在没使用AOP之前,如图一所示,骑士服务代码如下:
public class KnightOfTheRoundTable implements Knight { private Minstrel minstrel; public void setMinstrel(Minstrel minstrel){ this.minstrel=minstrel; } public Object embarkOnQuest() throws QuestFailedException { minstrel.singBefore(this);//任务前唱歌 HolyGail grail=quest.embark();//执行任务 minstrel.singAfter(this);//任务后唱歌 return grail; } } |
public class Minstrel { private static final Logger SONG = Logger.getLogger(Minstrel.class); public Minstrel() {} public void singBefore(Knight knight) { SONG.info("Fa la la; Sir " + knight.getName() + " is so brave!"); } public void singAfter(Knight knight) { SONG.info("Tee-hee-he; Sir " + knight.getName() + " did embark on a quest!"); } } |
<bean id="minstrel" class="com.springinaction.chapter01.knight.Minstrel"/> <aop:config> <aop:aspect ref="minstrel"> //创建切面,切面是歌者 <aop:pointcut id="questPointcut" expression="execution(* *.embarkOnQuest(..)) and target(bean)" /> //创建切入点,切入点是embarkOnQuest(),执行该方法即可触发该切入点 <aop:before method="singBefore" pointcut-ref="questPointcut" //在切入点之前执行singBefore方法 arg-names="bean" /> <aop:after-returning method="singAfter" //在切入点之前执行singAfter方法 pointcut-ref="questPointcut" arg-names="bean" /> </aop:aspect> </aop:config> |
public class KnightOfTheRoundTable implements Knight { private Quest quest; public Object embarkOnQuest() throws QuestFailedException { HolyGail grail=quest.embark();//执行任务 return grail; } } |