• 二十9天 月出冲击黑鸟 —Spring的AOP_AspectJ @annotation


                 6月14日,阴转雨。

    “四面垂杨十里荷,向云何处最花多, 画楼南畔夕阳和。天气乍凉人寂寞, 光阴须得酒消磨,且来花里听笙歌。” 

            面向切面的框架AspectJ邂逅Spring,不仅造就一种简洁,更带来很多其它的选择空间。

           上篇的切面与代理配置方式。麻烦且繁琐。好在Spring 与 AspectJ 进行了集成,从接口和配置的泥潭爬出,善莫大焉。偷笑

           以下把上一篇Spring的AOP 的样例改写一下,达到相同的效果。

           1-3步骤不变。
           4、定义一个 Aspect 切面类BallHandler.java

    package edu.eurasia.aop;
    
    import org.apache.log4j.Logger;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;  
    import org.aspectj.lang.annotation.Before;  
    import org.aspectj.lang.annotation.AfterReturning;  
    
    @Aspect
    public class BallHandler {
    	static Logger logger = Logger.getLogger(TestBall.class);
    	
    	@Pointcut("execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(..))")  
    	public void watchfootball(){};
    	
    	@Pointcut("execution(* edu.eurasia.aop.WatchBallImpl.watchbasket*(..))")  
    	public void watchbasketball(){};
    	
    	@Before(value="watchfootball()&& args(city,..)")  
            public void watchBefore(String city){  
           	      logger.debug(" 看球前,先去  " + city + "  咖啡馆喝杯巴西咖啡 ...");
    	}  
          
            @AfterReturning("watchbasketball() && args(city,..)")  
            public void watchAfter(String city){  
                  logger.debug("看完球去  " + city + "  麦当劳吃汉堡包!

    "); } }<span style="background-color: rgb(255, 255, 255);"> </span>

           类上面标注的 @Aspect 注解。这表明该类是一个 Aspect(事实上就是 Advisor)-切面类。

    该类无需实现不论什么的接口,仅仅需定义一个方法(方法叫什么名字都无所谓)。

           @Pointcut使用这种方法能够将edu.eurasia.aop.WatchBallImpl.watchfoot*(..)方法声明为poincut即切入点。作用,在watchfoot*(..)方法被调用的时候运行watchfootball()方法。当中execution是匹配方法运行的切入点。也就是spring最经常使用的切入点定义方式。

           @Before(value="watchfootball()&& args(city,..)):@Before声明为在切入点方法运行之前运行,而后面没有直接声明切入点,而是value="watchfootball()",是由于假设@afterReturning等都有所修改的时候都必须所有修改。所以统一用Pointcut的watchfootball取代,这样子有修改的时候仅需修改一个地方。其他@AfterReturning类同。&& args(city,..)能够获取切入点方法watchfoot*(..)的參数。


             以下分析一下这个切点表达式:

         execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(..))

    • execution():表示拦截方法,括号里可定义须要匹配的规则。

    • 第一个“*”:表示方法的返回值是随意的。

    • 第二个“*”:表示匹配该类中全部的方法。

    • (..):表示方法的參数是随意的。

           5、编写spring的配置文件applicationContext.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-2.0.xsd   
           http://www.springframework.org/schema/aop   
           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"   
    >
    
        <!-- 定义Aspect -->   
         <bean id="ballHandler" class="edu.eurasia.aop.BallHandler" />
      
        <!-- 定义Common -->   
         <bean id="watchBall" class="edu.eurasia.aop.WatchBallImpl" />   
      
        <!-- 启动AspectJ支持 -->   
        <aop:aspectj-autoproxy /> 
    </beans>
             6、编写測试类TestBall.java
    package edu.eurasia.aop;
    
    import org.apache.log4j.Logger;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestBall {
    	static Logger logger = Logger.getLogger(TestBall.class);
    
    	@Test
    	public void testball() {
    
    		logger.debug("test begin ");
    
    		ApplicationContext ctx = new ClassPathXmlApplicationContext(
    				"applicationContext.xml");
    		
    		WatchBall watchball = (WatchBall) ctx.getBean("watchBall");
    
    		watchball.watchfootball("里约热内卢");
    
    		logger.debug("----------------------------");
    
    		watchball.watchbasketball("德克萨斯州");
    	}
    }
             7、执行结果和环境配置

             执行结果例如以下:

    DEBUG [main] (BallHandler.java:21) -  看球前,先去  里约热内卢  咖啡馆喝杯巴西咖啡 ...
    DEBUG [main] (WatchBallImpl.java:11) - 去 里约热内卢 看2014巴西世界杯
    DEBUG [main] (TestBall.java:25) - ----------------------------
    DEBUG [main] (WatchBallImpl.java:16) -  去德克萨斯州 看2014NBA总决赛

    DEBUG [main] (BallHandler.java:26) - 看完球去  德克萨斯州  麦当劳吃汉堡包。

                本例使用spring 2.5.6,除了找出spring.jarcommons-logging-1.1.1.jar两个jar包,外加一个log4j.jar还要下载aspectj-1.7.0.jar。解压后有四个JAR:aspectjrt.jar,aspectjtools.jar,aspectjweaver.jarorg.aspectj.matcher.jar。还须要下载一个aopalliance-1.0.jar

                文件夹结构例如以下:

              8、基于配置的AspectJ           

             除了使用 @Aspect 注解来定义切面类以外,Spring AOP 也提供了基于配置的方式来定义切面类。

            (1) 配置文件applicationContext.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-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <!-- 定义Aspect --> <bean id="ballHandler" class="edu.eurasia.aop.BallHandler" /> <!-- 定义Common --> <bean id="watchBall" class="edu.eurasia.aop.WatchBallImpl" /> <aop:config> <aop:aspect ref="ballHandler"> <aop:before method="watchBefore" arg-names="city" pointcut="execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(String,..)) and args(city,..)" /> <aop:after method="watchAfter" arg-names="city" pointcut="execution(* edu.eurasia.aop.WatchBallImpl.watchbasket*(String,..)) and args(city,..)" /> </aop:aspect> </aop:config> </beans>

                 (String,..)声明切入点至少含有一个String类型的參数。显然能够匹配WatchBallImpl中的watchfoot*(String city,..);args(n,..)声明给watchfoot*(String city,..)的第一个參数起了个别名“n”传递给Advice,假设<aop:before...>中arg-names不是“n”,将抛出异常。

            (2) BallHandler.java 代码变化不大:

    package edu.eurasia.aop;
    
    import org.apache.log4j.Logger;  
    
    public class BallHandler {
    	static Logger logger = Logger.getLogger(TestBall.class);
    		
        public void watchBefore(String city){  
           	logger.debug(" 看球前。先去  " + city + "  咖啡馆喝杯巴西咖啡 ...");
    	}  
          
       
        public void watchAfter(String city){  
            logger.debug("看完球去  " + city + "  麦当劳吃汉堡包!");
        
        }  
    }
    
                (3)其余代码和配置不变,执行结果同样。




    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    HTTP POST GET 本质区别详解
    追求代码质量: 监视圈复杂度
    【置顶】用Eclipse开发Android应用程序索引贴
    Android访问WCF服务(上篇)服务端开发
    做一个T型技术人才
    创新创业大讲堂第一讲
    河海嵌芯FTP服务器开通运行
    嵌芯队团队邮箱以及邮件订阅功能使用说明
    基于视频的公共事件检测分析系统
    感知交通基于视频的交通流特征参数监测及交通综合信息服务系统
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4823311.html
Copyright © 2020-2023  润新知