OOP(Object Oriented Programming)面向对象编程解决了纵向上的层次分割,例如MVC模式将展现层、持久化层、逻辑处理层一一分开了,使得开发效率获得了较大提升,可是这只是纵向上的分割,若是从水平方向上来看,即若是一个项目中的不少类都须要实现某一个方法(例如:在网购平台上,登陆,下单,付款都须要对身份进行验证)若是要在这些类一一将这些都要执行的方法添加到其中这无疑将会增长代码量,这会使得程序显得很臃肿。基于以上的操做便诞生了咱们今天的主角----Spring-AOP。AOP即(Aspect Oriented Programming)面向切面编程。Spring-AOP就是实现一闪刚提出的问题。接下来咱们就为你们揭开Spring-AOP的“神秘面纱”。spring
1.1 什么是AOPexpress
AOP(Aspect Oriented Programming)面向切面编程,是对传统的OOP(ObjectOriented Programming)面向对象编程的补充。
1.2 AOP的做用编程
若是A,B,C三个方法都要在执行前作验证操做,执行后作日志打印操做。肿么办? ![图片描述][1]
1.3 AOP专业术语测试
切面(Aspect): A,B,C,方法执行前都要调用的验证逻辑和执行后都要调用的日志逻辑,这两个就是切面。
通知(Advice): 有五种通知,执行前,执行后,执行成功后,执行抛出异常后,环绕通知。就是切面执行的方法。
目标(Target): 被通知的对象,这里就是A,B,C三个方法。
链接点(Joinpoint):链接点是一个应用执行过程当中可以插入一个切面的点。
切点(pointcut):每一个类都拥有多个链接点,即链接点是程序类中客观存在的事务。AOP 经过切点定位到特定的链接点
打个比方:一天,三位侠客(被通知的对象Target)来我府上作客,被大门(切面Aspect)拦住,门前有五个保安(负责通知的Advice),由于其中一位侠客会降龙十八掌(知足被通知的一个条件Joinpoint),其中一位保安告知他:"你能够进去了"。另外两个侠客由于武艺超群(知足被通知的统一标准poincut)也都进去了。代理
下面咱们以一段实例来说解基于XML配置文件和基于注解的方式来讲明Spring-AOP的运行机制。
该程序的总体运行机制是:将入一个项目都想执行加、减、乘、除这四个方法,因此咱们将这四个操做封装在一个类中并将其做为一个切面,从而提升代码的复用率。日志
基于XML的使用code
//这个即是咱们的切面,即许多类要执行的方法
package com.zhangguo.Spring052.aop01;
public class Math {component
//加 public int add(int n1,int n2){ int result=n1+n2; System.out.println(n1+"+"+n2+"="+result); return result; } //减 public int sub(int n1,int n2){ int result=n1-n2; System.out.println(n1+"-"+n2+"="+result); return result; } //乘 public int mut(int n1,int n2){ int result=n1*n2; System.out.println(n1+"X"+n2+"="+result); return result; } //除 public int div(int n1,int n2){ int result=n1/n2; System.out.println(n1+"/"+n2+"="+result); return result; }
}xml
//这个就是通知啦,比如是上面所打比方的那五个门卫,全部类要使用上面的切面首先要通过这个类的“审核”对象
package com.zhangguo.Spring052.aop01; import org.aspectj.lang.JoinPoint; public class Advices { public void before(JoinPoint jp){ System.out.println("----------前置通知----------"); System.out.println(jp.getSignature().getName()); } public void after(JoinPoint jp){ System.out.println("----------最终通知----------"); } }
//下面咱们列出本实例的核心,XML配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 被代理对象 --> <!-- 此为在横向切面被统一抽象出来的方法 --> <bean id="math" class="com.zhangguo.Spring052.aop01.Math"></bean> <!-- 通知 --> <bean id="advices" class="com.zhangguo.Spring052.aop01.Advices"></bean> <!-- aop配置 --> <aop:config proxy-target-class="true"> <!--切面 --> <aop:aspect ref="advices"> <!-- 切点 -->
<aop:pointcut expression="execution( com.zhangguo.Spring052.aop01.Math.(..))"id="pointcut1"/>
<!--链接通知方法与切点 --> //当实现了通知中的before方法时执行切面中方法 <aop:before method="before" pointcut-ref="pointcut1"/> //当实现了通知中的after方法时执行切面中方法 <aop:after method="after" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config> </beans> //此为测试类 package com.zhangguo.Spring052.aop01; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop01.xml"); Math math = ctx.getBean("math", Math.class); int n1 = 100, n2 = 5; math.add(n1, n2); math.sub(n1, n2); math.mut(n1, n2); math.div(n1, n2); } }
基于注解的使用
package com.zhangguo.Spring052.aop02; import org.springframework.stereotype.Service; //此处使用@Service说明该类为切面 @Service("math") public class Math{ //加 public int add(int n1,int n2){ int result=n1+n2; System.out.println(n1+"+"+n2+"="+result); return result; } //减 public int sub(int n1,int n2){ int result=n1-n2; System.out.println(n1+"-"+n2+"="+result); return result; } //乘 public int mut(int n1,int n2){ int result=n1*n2; System.out.println(n1+"X"+n2+"="+result); return result; } //除 public int div(int n1,int n2){ int result=n1/n2; System.out.println(n1+"/"+n2+"="+result); return result; } } package com.zhangguo.Spring052.aop02; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class Advices { //此注解能够将Advices设置为通知类,即当使用到before方法时,便执行execution方括号中的号码 @Before("execution(* com.zhangguo.Spring052.aop02.Math.*(..))") public void before(JoinPoint jp){ System.out.println("----------前置通知----------"); System.out.println(jp.getSignature().getName()); } @After("execution(* com.zhangguo.Spring052.aop02.Math.*(..))") public void after(JoinPoint jp){ System.out.println("----------最终通知----------"); } } <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <context:component-scan base-package="com.zhangguo.Spring052.aop02"> </context:component-scan> <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans> //测试类 package com.zhangguo.Spring052.aop02; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop02.xml"); Math math = ctx.getBean("math", Math.class); int n1 = 100, n2 = 5; math.add(n1, n2); math.sub(n1, n2); math.mut(n1, n2); math.div(n1, n2); } }
最后附上项目源码地址:
连接:http://pan.baidu.com/s/1hrQIdvu 密码:eknb