• spring切面编程AOP 范例一


    参照网上的spring AOP编程实例进行配置,但是碰到了几个坑。这篇文章重点讲解一下我踩过的两个坑:

    1.使用@Service自动装配的时候,基础扫描包配置要正确;

    2.xml中切面配置中的execution表达式的匹配规则要注意;

    针对第一个问题

    是我发现我新建的一个包里面写了一个接口和这个接口的实现,在接口实现上使用@Service,那么在使用这个service的时候,bean会自动注入进来的,但是我写的单测用例一直提示我bean注入失败。我写的其他包里的service就可以正常使用。我突然想起来,spring要识别@Service,是需要扫描基础包的,那应该是我的基础包配置没有将我新建的这个包包含进去。

    applicationContext.xml中最初的配置:  

     <context:component-scan base-package="com.nuomi"/>

    而我新建的包名是:com.baidu.nuomi.crm.mm,果然是不包含在基础包里面的,于是我在applicationContext.xml配置文件中又新加了下面这一行:

    <context:component-scan base-package="com.baidu"/>

    就可以了。第一个问题完美解决。

    下面说下第二个问题

    第一步:写好切面类:

     1 package com.baidu.nuomi.crm.helper.monitorproxy.aspect;
     2 
     3 import org.aspectj.lang.JoinPoint;
     4 import org.aspectj.lang.ProceedingJoinPoint;
     5 
     6 /**
     7  * @author sonofelice
     8  * @version 2015年12月17日 下午1:21:46 类说明 :
     9  */
    10 public class ProxyAspect {
    11     public void doAfter(JoinPoint jp) {
    12         System.out.println("log Ending method:" + jp.getTarget().getClass().getName() + "."
    13                 + jp.getSignature().getName());
    14     }
    15 
    16     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    17         long time = System.currentTimeMillis();
    18         Object retVal = pjp.proceed();
    19         time = System.currentTimeMillis() - time;
    20         System.out.println("process time:" + time + "ms");
    21         return retVal;
    22     }
    23 
    24     public void doBefore(JoinPoint jp) {
    25         System.out.println("long Beginning methoe:" + jp.getTarget().getClass().getName() + "."
    26                 + jp.getSignature().getName());
    27     }
    28 
    29     public void doThrowing(JoinPoint jp, Throwable ex) {
    30         System.out.println("methoe" + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName()
    31                 + " throw exception");
    32         System.out.println(ex.getMessage());
    33     }
    34 }
    View Code

    第二步:写好切面要织入的目标对像:

    接口和其对应的实现:

     1 package com.baidu.nuomi.crm.target.asp;
     2 
     3 /**
     4  * @author sonofelice
     5  * @version 2015年12月17日 下午2:49:20 类说明 :
     6  */
     7 public interface AService {
     8 
     9     public void barA();
    10 
    11     public void fooA(String _msg);
    12 }
    13 
    14 package com.baidu.nuomi.crm.target.asp;
    15 
    16 import org.springframework.stereotype.Service;
    17 
    18 /**
    19  * @author sonofelice
    20  * @version 2015年12月17日 下午3:41:05 类说明 :
    21  */
    22 @Service("aService")
    23 public class AServiceImp implements AService {
    24 
    25     @Override
    26     public void barA() {
    27         System.out.println("AServiceImpl.barA()");
    28     }
    29 
    30     @Override
    31     public void fooA(String _msg) {
    32         System.out.println("AServiceImpl.fooA(msg:" + _msg + ")");
    33     }
    34 
    35 }
    View Code

    第三步:xml文件配置:

    首先在spring相关的配置文件中新建一个spring-aspect.xml文件:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xmlns:aop="http://www.springframework.org/schema/aop"
     5        xsi:schemaLocation="http://www.springframework.org/schema/beans
     6       http://www.springframework.org/schema/beans/spring-beans.xsd
     7       http://www.springframework.org/schema/aop
     8       http://www.springframework.org/schema/aop/spring-aop.xsd
     9              ">
    10     <bean id="proxyAspect" class="com.baidu.nuomi.crm.helper.monitorproxy.aspect.ProxyAspect"/>
    11     <aop:config>
    12         <aop:aspect id="doOpAspect" ref="proxyAspect">
    13             <aop:pointcut id="entrance" expression="execution(* com.baidu.nuomi.crm.target.asp.*.*(..))" />
    14             <aop:before pointcut-ref="entrance" method="doBefore"/> 
    15             <aop:after pointcut-ref="entrance" method="doAfter"/>
    16             <aop:around pointcut-ref="entrance" method="doAround"/>
    17             <aop:after-throwing pointcut-ref="entrance" method="doThrowing" throwing="ex"/>
    18         </aop:aspect>
    19     </aop:config>
    20 </beans>

    然后在applicationContext.xml文件中引入上面的配置文件:

    1 <import resource="spring-monitorproxy.xml" />

    第四步:写个单测用例看一下配置是否成功了(我用的是junit)

    下面是我的单测用例:

    1 public class BServiceTest extends BaseTest {
    2     @Autowired
    3     AService aService;
    4     @Test
    5     public void test() {
    6         aService.barA();
    7         aService.fooA("msg");
    8     }
    9 }

    运行结果如下:

    long Beginning methoe:com.baidu.nuomi.crm.target.asp.AServiceImp.barA

    AServiceImpl.barA()

    process time:0ms

    log Ending method:com.baidu.nuomi.crm.target.asp.AServiceImp.barA

    long Beginning methoe:com.baidu.nuomi.crm.target.asp.AServiceImp.fooA

    AServiceImpl.fooA(msg:msg)

    process time:0ms

    log Ending method:com.baidu.nuomi.crm.target.asp.AServiceImp.fooA

    当然,一开始肯定不是这么顺利的出结果的。切面类中的方法中打印的东西在我的控制台中一条都没有打印,这是为什么呢?肯定是切面类没有织入到目标类里面啊。仔细检查下配置文件,跟借鉴的别人的配置是一样的,配置第一行,都是先配置切面类的bean,不同的地方就是这个execution表达式

    <aop:pointcut id="entrance" expression="execution(* com.baidu.nuomi.crm.target.asp.*.*(..))" />

    那应该是我的表达式不正确。参考文章:http://lavasoft.blog.51cto.com/62575/172292/

    任意公共方法的执行:
    execution(public * *(..))
    任何一个名字以“set”开始的方法的执行:
    execution(* set*(..))
    AccountService接口定义的任意方法的执行:
    execution(* com.xyz.service.AccountService.*(..))
    在service包中定义的任意方法的执行:
    execution(* com.xyz.service.*.*(..))
    在service包或其子包中定义的任意方法的执行:
    execution(* com.xyz.service..*.*(..))

    我想要在包asp中的定义的任意方法上执行切面类,就按照对应的规则去配置才可以成功的。

    新手可以参考上面的配置,有问题可以留言。

     

     

  • 相关阅读:
    php总结4——数组的定义及函数、冒泡排序
    php总结3——基本函数、流程控制中的循环
    php总结2——php中的变量、数据类型及转换、运算符、流程控制中的分支结构
    php总结1 ——php简介、工作原理、运行环境、文件构成、语法结构、注释
    php中$t=date()函数参数意义及时间更改
    80端口未被占用,apache无法启动,命令行运行httpd.exe提示文档内容有错
    创建node.js一个简单的应用实例
    windows系统下nodejs、npm、express的下载和安装教程——2016.11.09
    前端工程师必备技能
    用于string对象中字符截取的几种函数总结——语法、参数意义及用途举例
  • 原文地址:https://www.cnblogs.com/sonofelice/p/5054643.html
Copyright © 2020-2023  润新知