这里先占个位置,今天晚上下班后完成!
痛苦啊!我们被困在办公室里了!一开门就走吧。只是可惜今天没有写这篇文章了!唉,计划不如变化快啊!
还没写这篇文章呢?就要催着走!
今天补上这一篇的内容:
目录:
1、AOP的原理
2、AOP的使用
1、AOP原理:
AOP编程是面向对象思维方式的有力补充。
面向切面编程就是在要运行的代码 前、后 加一些信息代码,而不影响原来的代码。
如果在框架中,没有AOP的这部分框架,我们自己也可以是实现面向切面编程----有两种比较好的方式:继承方式和组合设计模式
package com.longkun.aop.test; public class Algorithm { /** * @author longkun.wyb * 求一组数据的逆序数,归并排序 * @param args */ static int num = 0; public void main(){ System.out.println(2.00-1.10); System.out.printf("%.2f\n",2.00-1.10); int value[] = {0,10,100,45,39}; int left = 0; int right = value.length-1; mergeSort(value,left,right); System.out.println(num); for(int i = 0 ; i <= right; ++i){ System.out.print(" "+value[i]); } } private void mergeSort(int[] value,int left,int right){ if(left<right){ int middle = (left+right)/2; mergeSort(value,left,middle); mergeSort(value,middle+1,right); merge(value,left,middle,right); } } private void merge(int[] value,int left,int middle,int right){ int[] tmp = new int[100]; int k = left; int i = left; int j = middle+1; for(; i <= middle && j<= right ;){ if(value[i] > value[j]){ num+=middle-i+1; tmp[k++]=value[j++]; }else{ tmp[k++]=value[i++]; } } while(i<=middle){ tmp[k++]=value[i++]; } while(j<=right){ tmp[k++]=value[j++]; } for(i=left;i<=right;++i){ value[i]=tmp[i]; } } }
package com.longkun.aop.test; public class AlgorithmLog extends Algorithm{ @Override public void main() { System.out.println("log... start ..."); super.main(); System.out.println("log... end ..."); } }
package com.longkun.aop.test; public class AlgorithmRuntime extends AlgorithmLog{ @Override public void main() { System.out.println("Run start ..."); long start = System.currentTimeMillis(); super.main(); long end = System.currentTimeMillis(); System.out.println("Run end..."+" 时间:"+(end-start)); } }
问题来了,你如过想让RunTime在前,Log再后,那改代码就很麻烦了。需要让Algorithm继承AlgorithmRuntime等一系列。
于是我们使用一种设计模式,聚合设计模式----这种方法只是客户使用端的排列使用,相对简单了许多
首先建一个接口AlgorithmInterface,都去实现它。
看代码:
package com.longkun.aop.test; public interface AlgorithmInterface { public void main(); }一个主要的实现类,核心代码:
package com.longkun.aop.test; public class Algorithm implements AlgorithmInterface{ public void main(){ System.out.println("求一组数据的逆序数,归并排序"); } }一些切面上的代码:
log
package com.longkun.aop.test; public class AlgorithmLog implements AlgorithmInterface{ AlgorithmInterface al = null; public AlgorithmLog(AlgorithmInterface algorithm){ this.al = algorithm; } @Override public void main() { System.out.println("log... start ..."); al.main(); System.out.println("log... end ..."); } }
package com.longkun.aop.test; public class AlgorithmRuntime implements AlgorithmInterface{ AlgorithmInterface al = null; public AlgorithmRuntime(AlgorithmInterface algorithm) { this.al = algorithm; } @Override public void main() { System.out.println("Run start ..."); long start = System.currentTimeMillis(); al.main(); long end = System.currentTimeMillis(); System.out.println("Run end..."+" 时间:"+(end-start)); } }
package com.longkun.aop.test; public class Client { public static void main(String[] args){ AlgorithmInterface al = new Algorithm(); AlgorithmInterface log = new AlgorithmLog(al); AlgorithmInterface runtime = new AlgorithmRuntime(log); runtime.main(); System.out.println("************************************************"); AlgorithmInterface runtime1 = new AlgorithmRuntime(al); AlgorithmInterface log1 = new AlgorithmLog(runtime1); log1.main(); } } 执行结果: Run start ... log... start ... 求一组数据的逆序数,归并排序 log... end ... Run end... 时间:0 ************************************************ log... start ... Run start ... 求一组数据的逆序数,归并排序 Run end... 时间:0 log... end ...
在spring中的AOP的实现工程呢,则是使用动态代理的方式,比聚合设计模式还要简单一些,实现过程没有去模仿。在这里就说明一下使用。
2、AOP的使用
AOP的使用,分为注解注入方式(@AspectJ)和配置文件注入方式,由于AOP的注解方式很少用,并有一些不方便,所以这里讲解一下xml配置文件的注入使用方式。
几个简单的概念:
切面(Aspect)是现实世界领域问题的抽象,除了包括属性、方法以外,同时切面中还包括切入点 Pointcut、增强(advice)等。
连接点(Join point):连接点也就是运用程序执行过程中需要插入切面模块的某一点
切入点(Pointcut):切入点指一个或多个连接点,可以理解成一个点的集合。切入点一般会跟连接点的上下文环境结合
增强或通知(Advice):定义了切面中的实际逻辑(即实现),是指在定义好的切入点处,所要执行的程序代码。
一个样例:
beans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
<bean id="algorithm" class="com.longkun.aop.test.Algorithm"></bean>
<bean id="algorithmLog" class="com.longkun.aop.test.AlgorithmLog"/>
<aop:config>
<aop:aspect ref="algorithmLog">
<aop:before method="beforeMain" pointcut="execution(public * com.longkun.aop.test..*.*(..))"/>
<!-- 第一个*代表任何返回类型,第二个*代表com.longkun.aop.test包以及子包的任何类,第三个*代码任何方法 -->
<aop:after-returning method="afterReturnMain" pointcut="execution(public * com.longkun.aop.test.Algorithm.main(..))" returning="reval"/>
<aop:after method="afterMain" pointcut="execution(public void com.longkun.aop.test..*.main(..))"/>
<aop:after-throwing method="afterThrowingMain" pointcut="execution(public * com.longkun.aop.test.Algorithm.main(..))" throwing="ex"/>
<aop:around method="aroundMain" pointcut="execution(public * com.longkun.aop.test..*.display(..))"/>
</aop:aspect>
</aop:config>
</beans>
使用到动态的代理一定要用接口:
package com.longkun.aop.test; public interface AlgorithmInterface { public void main(); public void display(); }
package com.longkun.aop.test; public class Algorithm implements AlgorithmInterface{ public void display() { System.out.println("display......。。。。。。"); } public void main(){ System.out.println("求一组数据的逆序数,归并排序。。。。。。。"); } }
package com.longkun.aop.test; import org.aspectj.lang.ProceedingJoinPoint; public class AlgorithmLog{ public AlgorithmLog(){} public void beforeMain(){ System.out.println("beforeMain ... beforeMain"); } public void afterMain(){ System.out.println("afterMain ... afterMain:"); } public void afterReturnMain(String reval){ System.out.println("afterReturnMain ... afterReturnMain:"+reval); } public void afterThrowingMain(Exception ex){ System.out.println("afterThrowingMain:"+ex.getMessage()); } public void aroundMain(ProceedingJoinPoint joinPoint){ System.out.println("Aruound Before.."); try { joinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("Around After!!"); } }应用客户端实现:
package com.nullf; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.longkun.aop.test.AlgorithmInterface; public class Client { public static void main(String[] args){ ApplicationContext acx = new ClassPathXmlApplicationContext("beans.xml"); AlgorithmInterface al = (AlgorithmInterface)acx.getBean("algorithm"); System.out.println("hello main"); al.main(); // al.display(); } }
hello main beforeMain ... beforeMain beforeMain ... beforeMain 求一组数据的逆序数,归并排序。。。。。。。 afterReturnMain ... afterReturnMain:null afterMain ... afterMain: afterMain ... afterMain:
beforeMain ... beforeMain
afterMain ... afterMain:
这两句话出现两次,是因为com.longkun.aop.test包及子包下,有多个方法。
<aop:before method="beforeMain" pointcut="execution(public * com.longkun.aop.test..*.*(..))"/>
将这句话改为:
<aop:before method="beforeMain" pointcut="execution(public * com.longkun.aop.test.Algorithm.*(..))"/>
beforeMain ... beforeMain 这句话就会只出现一次