Spring AOP技术

[color=red][size=large]spring AOP技术[/size][/color]


6.通知应用实例(基于注解)

在前一节,我们应用了前置通知和后置通知,除了这两个通知外,下面接着演示其它通知的应用。

(1)最终通知

在切面类TheInterceptor中增加如下代码即可:略去测试。
@After("anyMethod()")// 最终通知

public void after() {

System.out.println("最终通知");

}

(2)异常通知

为了演示此实例,我们在UseDaoImp中增加如下代码以抛出异常:

int i=1/0;在然后在切面类TheInterceptor中增加如下代码:
@AfterThrowing("anyMethod()") // 例外通知

public void AfterThrowing() {

System.out.println("例外通知");

}
当获取代理对象并调用save方法时会抛出异常,例外通知便会得以执行。

(3)环绕通知

@Around("anyMethod()") //环绕通知

public Object around(ProceedingJoinPoint pjp) throws Throwable {

System.out.println("进入环绕");

//if(){ // 进行一些判断,再执行环绕

Object result = pjp.proceed();

//}

System.out.println("退出环绕");

return result;

}
注意的是方法的参数及抛出异常类型的固定写法(方法名可以是任意得),另在该方法中必须执行pjp.proceed()才能让环绕通知中的两处打印代码得以执行。即是说要想环绕通知的拦截处理代码起作用必须调用pjp.proceed方法。 补充:环绕通知通常可以用来测试方法的执行时间,在pjp.proceed前获取一个时间,在pjp.proceed方法后再获取一个时间。最后两个时间相减即可得方法执行时间。

(4)传递参数给通知

首先在UseDao接口中增加如下代码:
String add(String name);
然后再在UserDaoImp中实现此方法,代码如下:
public String add(String name) {

System.out.println("add method is called [ " + name+" ]");

return "添加成功";

}
需求:获取调用add方法传递的参数。操作步骤如下:在切面类增加如下代码:
@Before("anyMethod() && args(name)")// 前置通知,只针对UseDaoImp的add方法

public void beforeAdd(String name) {

System.out.println("前置通知:" + name);

}
说明:在前置通知的方法中有一个参数,然后再把此参数作为拦截条件(即是说拦截带有一个String类型参数的方法)。args的名字和beforeAdd方法参数名字相同。
测试代码:
public void advieeTest() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserDao ud=(UserDao) ctx.getBean("userDaoImp");

ud.add("xxx");

}

(5)获取方法的返回值

我们知道add方法有一个返回值,我们对此方法进行拦截并获取返回值,在切面类中增加如下代码:
@AfterReturning(pointcut = "anyMethod()", returning = "result")

// 后置通知,监听返回结果,针对UserDaoImp的getUsername()方法

public void afterReturningRes(String result) {

System.out.println("后置通知,返回结果:" + result);

}
说明:afterReturningRes方法的参数就是要返回的参数类型,returning标记的就是的结果,它的取值与该方法参数名相同。 测试代码同(4)。

(6)获取抛出的异常

切面类的增加如下代码:

@AfterThrowing(pointcut="anyMethod",throwing="e")

public void catchException(Exception e){

System.out.println("获取抛出的异常:"+e);

}
throwing的取值和方法的参数名相同,测试代码省略。

7. 通知应用实例(基于XML)

步骤一、复制TheInterceptorX类为TheInterceptorXML,并去掉所有注解。

步骤二、建立beansXML.xml配置文件,内容如下:
<aop:aspectj-autoproxy /><!-- 开启切面编程功能 -->

<bean id="userDaoImp" class="com.asm.dao.impl.UserDaoImp" />

<bean id="aspectBean"

class="com.asm.dao.impl.factory.TheInterceptorXML" />

<aop:config>

<aop:aspect id="asp" ref="aspectBean"> --声明一个切面类

<aop:pointcut id="thecut" --声明一个切入点

expression="execution(* com.asm.dao.impl.UserDaoImp.*(..))" />

<aop:after-returning pointcut-ref="thecut" method="afterReturningRes" returning="result" />

<aop:around pointcut-ref="thecut" method="around"/>

<aop:after-throwing pointcut-ref="thecut" method="catchException" throwing="e"/>

<aop:after pointcut-ref="thecut" method="after" />

<aop:before pointcut-ref="thecut" method="before" />

</aop:aspect>

</aop:config>

测试代码如下:
public void advieeTest() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beansXML.xml");

UserDao ud=(UserDao) ctx.getBean("userDaoImp");

ud.add("xxx");

}
未解决问题:不能成功传参给前置通知。

8.解析切入点表达式

1.格式:execution(返回值 空格 方法选择)。两部分组成,中间一定要有空格。
返回值:可以是*,说明拦截任何方法。Java.lang.String(全名),拦截返回值为String类型的方法。 常用的实例如下:

方法选择:包名[类名].*()。设定要拦截的方法签名。

表达式(省略execution)


说明

(java.lang.String 方法选择略)


拦截返回值为String类型的方法

(!void 方法选择略)


拦截返回值非空的方法

(* com.asm..*.*(..))


拦截com.asm包及子包下每个类的全部方法

(* com.asm.*.*(..))


拦截com.asm包下每个类的全部方法

(* com.asm.User.*(..))


拦截asm包下User类的所有方法

(* com.asm.User.*
(java.lang.String,..))


拦截User类中第一个参数为String,后面参数任一的方法

待增加




待增加




9.总结

面向切面的常见应用(如权限拦截)、spring的aop依赖两种方式实现代理(依被代理的对象是否实现接口而定)、通知概念、基于注解与基于XML两种方式来配置切面、基本步骤(依要拦截的方法来设定切入点,依据业务需求实现拦截通知代码,切面纳入spring容器管理,要被监控的类只能是通过Spring容器获取)、切入点的格式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值