这里先占个位置,今天晚上下班后完成!
痛苦啊!我们被困在办公室里了!一开门就走吧。只是可惜今天没有写这篇文章了!唉,计划不如变化快啊!
还没写这篇文章呢?就要催着走!
今天补上这一篇的内容:
目录:
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];
}
}
}
在这段代码前后加代码的话,可以继承这个类,调用super的方式:
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 ...");
}
}
runtime:
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;
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 这句话就会只出现一次