http://blog.csdn.net/yerenyuan_pku/article/details/52879669

前面我们已经入门使用Spring的注解方式实现AOP了,现在我们再来学习使用Spring的注解方式实现AOP的一些细节。本文是建立在使用Spring的注解方式实现AOP入门的案例的基础之上的。 
本文是来讲解使用Spring的注解方式实现AOP的一些细节,其实说白了就是学习如何使用各种通知而已,例如前置通知、后置通知、异常通知、最终通知、环绕通知等,之前我们已经学习了前置通知,现在就来学习剩余的通知。 
我们先来看后置通知,此时须将MyInterceptor类的代码修改为:

/**
* 切面
* @author li ayun
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceImpl.*(..))")
private void anyMethod() {} // 声明一个切入点,anyMethod为切入点名称 // 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知");
} @AfterReturning("anyMethod()")
public void doAfterReturning() {
System.out.println("后置通知");
} }
  • 1

测试SpringAOPTest类的interceptorTest()方法,可以发现Eclipse控制台打印: 
 
这说明后置通知方法是在目标方法执行之后执行的。 
我们再来看最终通知,此时须将MyInterceptor类的代码修改为:

/**
* 切面
* @author li ayun
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceImpl.*(..))")
private void anyMethod() {} // 声明一个切入点,anyMethod为切入点名称 // 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知");
} @AfterReturning("anyMethod()")
public void doAfterReturning() {
System.out.println("后置通知");
} @After("anyMethod()")
public void doAfter() {
System.out.println("最终通知");
}
}
  • 1

测试SpringAOPTest类的interceptorTest()方法,可以发现Eclipse控制台打印: 
 
再接者,我们来看一下异常通知,异常通知是在目标方法抛异常时执行的,故我们应将PersonServiceImpl类的代码改为:

public class PersonServiceImpl implements PersonService {

    @Override
public void save(String name) {
throw new RuntimeException("我是异常");
// System.out.println("我是save()方法");
} @Override
public void update(String name, Integer id) {
System.out.println("我是update()方法");
} @Override
public String getPersonName(Integer id) {
System.out.println("我是getPersonName()方法");
return "xxx";
} }
  • 1

然后在MyInterceptor类中声明异常通知方法:

/**
* 切面
* @author li ayun
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceImpl.*(..))")
private void anyMethod() {} // 声明一个切入点,anyMethod为切入点名称 // 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知");
} @AfterReturning("anyMethod()")
public void doAfterReturning() {
System.out.println("后置通知");
} @After("anyMethod()")
public void doAfter() {
System.out.println("最终通知");
} @AfterThrowing("anyMethod()")
public void doAfterThrowing() {
System.out.println("异常通知");
}
}
  • 1

测试SpringAOPTest类的interceptorTest()方法,可以发现Eclipse控制台打印: 
 
并且还抛出异常。 
最后,我们来看一下环绕通知,Struts2提供的拦截器就属于环绕通知,环绕通知在我们做权限系统时将大量使用。这时,我们还是将PersonServiceImpl类的代码恢复为:

public class PersonServiceImpl implements PersonService {

    @Override
public void save(String name) {
// throw new RuntimeException("我是异常");
System.out.println("我是save()方法");
} @Override
public void update(String name, Integer id) {
System.out.println("我是update()方法");
} @Override
public String getPersonName(Integer id) {
System.out.println("我是getPersonName()方法");
return "xxx";
} }
  • 1

然后在MyInterceptor类中声明环绕通知方法,环绕通知方法的写法是固定的,形如:

public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
...
}

这样,MyInterceptor类的代码应该是:

/**
* 切面
* @author li ayun
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceImpl.*(..))")
private void anyMethod() {} // 声明一个切入点,anyMethod为切入点名称 // 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知");
} @AfterReturning("anyMethod()")
public void doAfterReturning() {
System.out.println("后置通知");
} @After("anyMethod()")
public void doAfter() {
System.out.println("最终通知");
} @AfterThrowing("anyMethod()")
public void doAfterThrowing() {
System.out.println("异常通知");
} @Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
/**
* 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
* 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
* 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
*/
// if () { // 判断用户是否有权限,
System.out.println("进入方法");
Object result = pjp.proceed();
System.out.println("退出方法");
// }
return result;
}
}
  • 1

注意:环绕通知内部一定要确保执行proceed()该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。 
其实我们仅使用环绕通知就可以实现前置通知、后置通知、异常通知、最终通知等的效果。 
测试SpringAOPTest类的interceptorTest()方法,可以发现Eclipse控制台打印: 

前面部分我们已经学会了如何使用各种通知,例如前置通知、后置通知、异常通知、最终通知、环绕通知等,现在我们再来看使用Spring的注解方式实现AOP的另一些细节。 
细节一:如果我需要得到输入参数,如在前置通知里面,得到用户输入的数据。此时,须将前置通知方法修改为:

@Before("anyMethod() && args(name)")
public void doAccessCheck(String name) {
System.out.println("前置通知:" + name);
}

@Before("anyMethod() && args(name)")匹配的是PersonServiceImpl类中参数为String类型的方法,即save()方法。 
测试SpringAOPTest类的interceptorTest()方法,可以发现Eclipse控制台打印: 
 
细节二:如我要获得PersonServiceImpl类中的getPersonName()方法的返回参数。此时,须将后置通知方法修改为:

@AfterReturning(pointcut="anyMethod()", returning="result")
public void doAfterReturning(String result) {
System.out.println("后置通知:" + result);
}

@AfterReturning(pointcut="anyMethod()", returning="result")匹配的是PersonServiceImpl类中返回值类型为String的方法,并且returning属性能将返回值传入进后置通知方法里面。 
我们还要修改SpringAOPTest类的代码为:

public class SpringAOPTest {

    @Test
public void interceptorTest() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) cxt.getBean("personService");
personService.getPersonName(2);
} }
  • 1

测试interceptorTest()方法,可以发现Eclipse控制台打印: 
 
细节三:在目标方法出现异常时,得到抛出的异常。为了便于试验,我们须将PersonServiceImpl类的代码修改为:

public class PersonServiceImpl implements PersonService {

    @Override
public void save(String name) {
throw new RuntimeException("我是异常");
// System.out.println("我是save()方法");
} @Override
public void update(String name, Integer id) {
System.out.println("我是update()方法");
} @Override
public String getPersonName(Integer id) {
System.out.println("我是getPersonName()方法");
return "xxx";
} }
  • 1

然后将异常通知方法修改为:

@AfterThrowing(pointcut="anyMethod()", throwing="e")
public void doAfterThrowing(Exception e) {
System.out.println("异常通知:" + e);
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

最后,我们还要将SpringAOPTest类的代码改为:

public class SpringAOPTest {

    @Test
public void interceptorTest() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) cxt.getBean("personService");
personService.save("xxx");
} }
  • 1

测试interceptorTest()方法,可以发现Eclipse控制台打印: 
 
基于Spring的注解方式实现AOP就学习到这里。如须查看源码,可点击使用Spring的注解方式实现AOP的细节进行下载。

 
 

(转)使用Spring的注解方式实现AOP的细节的更多相关文章

  1. (转)使用Spring的注解方式实现AOP入门

    http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...

  2. Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...

  3. 使用Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...

  4. spring 纯注解方式 与AOP

    spring注解方式 以前我也使用过纯注解方式.现在在这里做个记录 我们先认识几个我们都耳熟能详的注解 @configuration :从spring3.0这个注解就可以用于定义配置类,可以替换xml ...

  5. Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop

    Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...

  6. 基于AspectJ的注解方式进行AOP开发

    -------------------siwuxie095                                     基于 AspectJ 的注解方式进行 AOP 开发         ...

  7. 使用注解方式实现 AOP和IoC

    使用注解方式实现AOP和IoC IOC和DI的注解 IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Servic ...

  8. mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类

    相信大家在刚开始学习mybatis注解方式,或者spring+mybatis注解方式的时候,一定会有一个疑问,为什么mybatis的dao接口只需要一个接口,不需要实现类,就可以正常使用,笔者最开始的 ...

  9. spring事务管理方式,aop

    达内12 note unit 09 01 1.spring事务管理 2.spring提供了对事务管理支持 spring采用aop机制完成事务控制 可以实现在不修改原有组件代码情况下实现事务控制功能. ...

随机推荐

  1. NSError分析

    在iOS开发中,NSError的使用非常常见,使用也比较简单,也正因为简单,所以对这一部分知识不甚注重.但是近期在做app底层网络封装时发现了一些问题.我使用的网络框架是AFNetworking,AF ...

  2. Linux Cache 机制

    在阅读文章前,您应该具备基本的存储器层次结构知识,至少要了解局部性原理.要详细了解cache基本原理,可以参考本书<深入理解计算机系统>中存储器体系结构一章: 带着疑问来看文章,cache ...

  3. iOS copy/retain/assign

    1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1 2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retai ...

  4. 从1到N的整数中1出现的次数

    /* * 1-n整数中1出现的次数.cpp * * Created on: 2018年5月1日 * Author: soyo */ #include<iostream> using nam ...

  5. Gradle系列之三 Gradle概述以及生命周期

    1 Gradle是一种编程框架 gradle主要由以下三部分组成 1 groovy核心语法 2 build script block 3 gradle api 注:本章所有的代码都在 https:// ...

  6. UIScrollView控件实现图片轮播

    http://www.cnblogs.com/dyf520/p/3805297.html 一.实现效果 实现图片的自动轮播            二.实现代码 storyboard中布局 代码: 1 ...

  7. jQuery笔记之遍历索引(补充)

    遍历索引的相关方法: .each() .补充.children() .index() --------------------------------------------------------- ...

  8. Asp.net core 框架整理

    https://github.com/thangchung/awesome-dotnet-core#cms

  9. Python递归和迭代

    递归 在函数内部,调用函数自身的编程技巧称为递归( recursion).递归函数结构清晰,很直观的理解计算过程,但也有严重缺点:相对于普通循环而言,递归运行效率较低,经过很多冗余的计算,递归会消耗大 ...

  10. Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) M

    Description The marmots have prepared a very easy problem for this year's HC2 – this one. It involve ...