示例展示
AOP(Aspect Oriented Programming),是面向切面编程的技术。AOP基于IoC基础,是对OOP的有益补充。
AOP之所以能得到广泛认可,主要是因为它将应用系统拆分分了2个部分:核心业务逻辑及横向的通用逻辑,也就是所谓的切面。例如,所有大中型应用都要涉及到的持久化管理、事务管理、权限管理、日志管理和调试管理等。使用AOP技术,可以让开发人员只专注核心业务,而通用逻辑则使用AOP技术进行横向切入,由专人去处理这些通用逻辑,会使得任务简单明了,提高开发和调试的效率。
下面我们来举个例子(具体代码参见右侧源码,只适合菜鸟看)
示例场景
场景:歌手演唱音乐,演唱之前观众要坐在座位上并且关闭手机,演唱结束后,观众们满意就鼓掌,不满意就抛出不高兴的异常。
分析这个场景,某歌手演唱音乐是核心业务逻辑,而演唱之前和之后观众们的动作都是通用的,属于横向的通用逻辑。
示例原理图
实现步骤
1.首先建立一个歌手接口 Performer。
2.再建立爵士音乐歌手类 DukePerformer 来实现这个接口,类中包括了歌手的个人信息。
3.然后定义观众类 Audience,包含观众的行为通知。
4.完成之后,我们便可以在配置文件 applicationContext.xml 中进行aop切面配置。关键代码如下:
<aop:config> <!-- 定义切入点 --> <aop:pointcut id="sing" expression="execution(* *.perform(..))"/> <!-- 定义切面 --> <aop:aspect ref="audience"> <!-- 前置通知 --> <aop:before method="takeSeat" pointcut-ref="sing" /> <aop:before method="turnOffPhone" pointcut-ref="sing" /> <!-- 返回后通知 --> <aop:after-returning method="applaud" pointcut-ref="sing" /> <!-- 抛出后通知 --> <aop:after-throwing method="unHappy" pointcut-ref="sing" /> </aop:aspect> </aop:config>
5.编写测试类代码,获得Spring中定义的Bean对象,执行perform表演方法,查看后台是如何运行的。
正常情况下,控制台会打印如下的信息:
观众坐在座位上。 观众关闭手机。 duke 开始演唱歌曲。 观众鼓掌,掌声经久不息...
知识准备
什么是AOP?
AOP: (Aspect Oriented Programming) 面向切面编程。是目前软件开发中的一个热点,也是Spring框架中容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
什么是OOP?AOP与其有什么区别?
AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。 而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。
通俗来讲,OOP面向名词领域,AOP面向动词领域。
如何理解AOP?
举个简单例子,比如你想在每次写字之前都检查一下笔里有没有墨水了,通常的做法是:在写字这个Action里调用判断是否有墨水的方法。这样做的不好一个方面是,写字的Action和是否有墨水的方法产生了依赖,如果你有十几支不同的笔写字,每一个笔的Action里都要调用判断是否有墨水的方法;另一个方面是:就面向对象的程序设计来说,写字和判断是否有墨水的方法是同一等级的,如果你让写字这个动作来判断是否有墨水不够人性化,有违面向对象的程序设计的思想。
如果用Spring的AOP,是把写字的Action作为一个切面,在每次调用不同的笔来写字的方法之前,调用判断是否有墨水的方法。它是由<aop:config/>标签在Spring配置文件里定义的。
资源准备
1:jar包下载地址:spring jar包
2.详细学习参考spring参考手册spring参考手册
示例
AOP的实现可以使用注解和xml配置文件两种方式,这里使用xml配置文件方式。示例的过程见左侧的“示例展示”,下面是源码:
首先建立一个接口Performer类
1 package demoinfo.spring.aop; 2 3 public interface Performer { 4 //表演歌曲 5 public void perform(); 6 }
再建立一个接口实现类DukePerformer
1 package demoinfo.spring.aop; 2 3 public class DukePerformer implements Performer{ 4 private String name; 5 public void setName(String name) { 6 this.name=name; 7 } 8 public String getName() { 9 return this.name; 10 } 11 public void perform() { 12 System.out.println(this.name+" 开始演唱歌曲。"); 13 } 14 }
Audience观众业务类
1 package demoinfo.spring.aop; 2 3 public class Audience { 4 public void takeSeat() { 5 System.out.println("观众坐在座位上。"); 6 } 7 public void turnOffPhone() { 8 System.out.println("观众关闭手机。"); 9 } 10 public void applaud() { 11 System.out.println("观众鼓掌,掌声经久不息..."); 12 } 13 public void unHappy() { 14 System.out.println("观众不高兴."); 15 } 16 }
配置文件applicationContext.xml代码如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 6 http://www.springframework.org/schema/aop 7 http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 8 <!-- AOP学习时的配置 --> 9 <bean id="DukePerformer" class="demoinfo.spring.aop.DukePerformer"> 10 <property name="name" value="duke" /> 11 </bean> 12 <bean id="audience" class="demoinfo.spring.aop.Audience" /> 13 14 <aop:config> 15 <!-- 定义切入点 --> 16 <aop:pointcut id="sing" expression="execution(* *.perform(..))"/> 17 <!-- 定义切面 --> 18 <aop:aspect ref="audience"> 19 <!-- 前置通知 --> 20 <aop:before method="takeSeat" pointcut-ref="sing" /> 21 <aop:before method="turnOffPhone" pointcut-ref="sing" /> 22 <!-- 返回后通知 --> 23 <aop:after-returning method="applaud" pointcut-ref="sing" /> 24 <!-- 抛出后通知 --> 25 <aop:after-throwing method="unHappy" pointcut-ref="sing" /> 26 </aop:aspect> 27 </aop:config> 28 <!-- AOP学习时的配置 --> 29 </beans>
最后测试类代码如下:
1 package demoinfo.spring.aop; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.FileSystemXmlApplicationContext; 5 6 public class SpringDemo { 7 public static void main(String[] args) { 8 //获得Spring中定义的Bean实例(对象) 9 ApplicationContext ctx=new FileSystemXmlApplicationContext( 10 "classpath:demoinfo/spring/aop/applicationContext.xml"); 11 Performer per=(Performer)ctx.getBean("DukePerformer"); 12 per.perform(); 13 } 14 }