Spring AOP AspectJ

Spring的AOP可以通过对@AspectJ注解的支持和在XML中配置来实现,本文通过实例简述如何在Spring中使用AspectJ.
一:使用AspectJ注解:
1,启用对AspectJ的支持:
通过在Spring的配置中引入下列元素来启用Spring对AspectJ的支持:

<aop:aspectj-autoproxy />

或者(如果不是使用XSD的话)

<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

2,声明一个带有@Aspect注解的类,在这个类中声明那些方法需要被'关注'(利用@Pointcut),在那些时机点进行关注(利用@Before,@AfterReturning等等...),执行'切入'的方法
3,在Spring的配置文件中定义这个'切面'类:任意带有一个@Aspect切面(拥有@Aspect注解)的bean都将被Spring自动识别并用于配置在Spring AOP.
4,使用被Spring管理的bean,在执行被'关注'的方法时,'切入'的方法就会被执行.
一个完整的例子:
需要被'切入'的类:

public class Monkey { public void stealPeaches(String name) {
        System.out.println(" Monkey " + name + " is stealling peaches...");
    } public void stealCorns(String name) {
        System.out.println(" Monkey " + name + " is stealling corns...");
    }
}

'切面'类:

@Aspect public class Guardian {
    @Pointcut("execution(* com.test.spring.aspectj.Monkey.stealPeaches(..))") public void guardOrchard() {
    }

    @Before(value = "guardOrchard()") public void guardOrchardBefore() {
        System.out.println("Guardian spotted a monkey is approaching the orchard...");
    }

    @AfterReturning("guardOrchard() && args(name,..)") public void guardOrchardAfter(String name) {
        System.out.println("Guardian caught a monkey stealling peaches whoes name is " + name + "...");
    }
   @Around("guardOrchard() && args(name,..)")   public void guardOrchardAround(ProceedingJoinPoint joinpoint,String name) {     System.out.println("Guardian guardOrchardAround started ... " + name);     try { joinpoint.proceed();     } catch (Throwable e) {       System.out.println("Guardian guardOrchardAround exception happened ... " + name);     }
    System.out.println("Guardian guardOrchardAround completed ... " + name);   }
    @Pointcut("execution(* com.test.spring.aspectj.Monkey.stealCorns(..))") public void guardFarm() {
    }

    @Before(value = "guardFarm()") public void guardFarmBefore() {
        System.out.println("Guardian spotted a monkey is approaching the farm...");
    }

    @AfterReturning("guardFarm() && args(name,..)") public void guardFarmAfter(String name) {
        System.out.println("Guardian caught a monkey stealling corns whoes name is " + name + "...");
    }
}

配置文件:

<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="    
         http://www.springframework.org/schema/beans    
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
         http://www.springframework.org/schema/aop    
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <!-- <aop:aspectj-autoproxy /> equals to <bean
        class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"
        /> -->
    <aop:aspectj-autoproxy />
    <bean id="guardian" class="com.test.spring.aspectj.Guardian" />

    <bean id="monkey" class="com.test.spring.aspectj.Monkey" />

</beans>

使用bean:

ApplicationContext context = new ClassPathXmlApplicationContext("conf/aspectJAppcontext.xml");
        Monkey monkey = (Monkey) context.getBean("monkey"); try {
            monkey.stealPeaches("mighty monkey");
            monkey.stealCorns("mighty monkey");
        } catch (Exception e) {
        }

运行结果:

Guardian spotted a monkey is approaching the orchard...
Guardian guardOrchardAround started ... mighty monkey 
Monkey mighty monkey is stealling peaches...
Guardian caught a monkey stealling peaches whoes name is mighty monkey...
Guardian guardOrchardAround completed ... mighty monkey
Guardian spotted a monkey is approaching the farm...
 Monkey mighty monkey is stealling corns...
Guardian caught a monkey stealling corns whoes name is mighty monkey...

二:通过XML配置AspectJ实现AOP:在java类中定义要被'方面'调用的切入方法,在XML中配置.
例子:被'切入'的类,普通java类:

public class Monkey { public void stealPeaches(String name) {
        System.out.println(" Monkey " + name + " is stealling peaches...");
    } public void stealCorns(String name,int numberToSteal) {
        System.out.println(" Monkey " + name + " is stealling corns...");
    }
}

定义要被'方面'调用的切入方法的类:

public class XMLGuardian { public void guardOrchardBefore() {
        System.out.println("XMLGuardian spotted a monkey is approaching the orchard...");
    } public void guardOrchardAfter() {
        System.out.println("XMLGuardian caught a monkey stealling peaches whoes name is ...");
    } public void guardFarmBefore() {
        System.out.println("XMLGuardian spotted a monkey is approaching the farm...");
    } public void guardFarmAfter(String name,int num,Object retVal) {
        System.out.println("XMLGuardian caught a monkey stealling " + num + " corns whoes name is ..." + name );
    }
}

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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="    
         http://www.springframework.org/schema/beans    
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
         http://www.springframework.org/schema/aop    
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="guardian" class="com.test.spring.aspectj.XMLGuardian" />
    <bean id="monkey" class="com.test.spring.aspectj.Monkey" />
    <aop:config>

        <aop:aspect id="myAspect" ref="guardian">
            <aop:pointcut id="guardOrchard" expression="execution(* com.test.spring.aspectj.Monkey.stealPeaches(..))" />

            <aop:before pointcut-ref="guardOrchard" method="guardOrchardBefore" />
            <aop:after-returning pointcut-ref="guardOrchard" method="guardOrchardAfter"/>

            <aop:pointcut id="guardFarm" expression="execution(* com.test.spring.aspectj.Monkey.stealCorns(..))" />

            <aop:before pointcut-ref="guardFarm" method="guardFarmBefore" />
            <aop:after-returning pointcut="execution(* com.test.spring.aspectj.Monkey.stealCorns(..)) and args(name,num,..)" returning="retVal" method="guardFarmAfter" />
            <!-- arg-names="name1" -->
        </aop:aspect>       
    </aop:config>
</beans>

客户端测试代码:

ApplicationContext context = new ClassPathXmlApplicationContext("conf/xmlaspectJAppcontext.xml");
        Monkey monkey = (Monkey) context.getBean("monkey"); try {
            monkey.stealPeaches("mighty monkey");
            monkey.stealCorns("mighty monkey",3);
        } catch (Exception e) {
        }

运行结果:

XMLGuardian spotted a monkey is approaching the orchard...
 Monkey mighty monkey is stealling peaches...
XMLGuardian caught a monkey stealling peaches whoes name is ...
XMLGuardian spotted a monkey is approaching the farm...
 Monkey mighty monkey is stealling corns...
XMLGuardian caught a monkey stealling 3 corns whoes name is ...mighty monkey

Spring AOP 只支持对bean的方法级的'切入',而且AOP的内部机制和AspectJ有所区别,Spring主要是通过动态代理来实现AOP,使用JDK的动态代理(如果被代理的bean是interface的话)或者CGLIB(如果如果被代理的bean不是interface的话).

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容

  • IoC 容器 Bean 的作用域 自定义作用域实现 org.springframework.beans.facto...
    Hsinwong阅读 2,475评论 0 7
  • 概述 Spring是什么? Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但是现在已经不止于企...
    琅筑阅读 1,170评论 2 8
  • 说明:本文主要内容来自慕课网。配合视频食用口味更佳。主要是顺着已经学习的视频顺序总结一遍,以深化理解和方便日后复习...
    stoneyang94阅读 852评论 3 5
  • 你什么时候才可以成功,这个问题问的似乎有些不恰当,什么叫什么时候才可以成功啊?这个问题问的不好,我们怎么知道什么时...
    庄德坤阅读 637评论 0 0
  • 每个杰出人物之所以能为人所知,之所以能超越他人,要点有三:有专项专业特长,顺应时代背景,有个人特质。而要快速变成杰...
    姚Fay阅读 170评论 0 0