http://outofmemory.cn/java/spring/AOP/aop-aspectj-example-before-after-AfterReturning-afterThrowing-around

我们介绍了spring aop相关的概念和aop注入表达式的示例,这里我们用一个完整的例子演示spring aspectj aop的使用。

首先新建一个maven项目,在项目的pom.xml中添加spring aop相关的依赖项:

如下是完整的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>cn.outofmemory</groupId>
<artifactId>spring-aop-aspect</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>spring-aop-aspect</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.1.1.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
</project>

在maven中我们引入了spring aop相关的依赖,aspectj相关的包有两个,cglib是必须的。

下面我们在项目中新建一个Service类PersonService,它是业务代码,是我们AOP注入的目标类:

package cn.outofmemory.spring_aop_aspect;

import org.springframework.stereotype.Service;

@Service
public class PersonService { public void addPerson(String personName) {
System.out.println("add person " + personName);
} public boolean deletePerson(String personName) {
System.out.println("delete person " + personName) ;
return true;
} public void editPerson(String personName) {
System.out.println("edit person " + personName);
throw new RuntimeException("edit person throw exception");
} }

PersonService类中定义了三个方法,addPerson方法无返回值,而deletePerson方法有返回值,而editPerson方法抛出运行时的异常。

下面我们看Aspect类:

package cn.outofmemory.spring_aop_aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; @Component
@Aspect
public class SimpleAspect {
@Pointcut("execution(* cn.outofmemory.spring_aop_aspect.*Service*.*(..))")
public void pointCut() {
} @After("pointCut()")
public void after(JoinPoint joinPoint) {
System.out.println("after aspect executed");
} @Before("pointCut()")
public void before(JoinPoint joinPoint) {
//如果需要这里可以取出参数进行处理
//Object[] args = joinPoint.getArgs();
System.out.println("before aspect executing");
} @AfterReturning(pointcut = "pointCut()", returning = "returnVal")
public void afterReturning(JoinPoint joinPoint, Object returnVal) {
System.out.println("afterReturning executed, return result is "
+ returnVal);
} @Around("pointCut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around start..");
try {
pjp.proceed();
} catch (Throwable ex) {
System.out.println("error in around");
throw ex;
}
System.out.println("around end");
} @AfterThrowing(pointcut = "pointCut()", throwing = "error")
public void afterThrowing(JoinPoint jp, Throwable error) {
System.out.println("error:" + error);
}
}

SimpleAspect类中的第一个方法是pointCut()方法,此方法无任何执行内容,只有一个@Pointcut的注解,其他方法都会引用这个注解中指定的pointcut表达式。

其他几个方法是各种Advice类型的方法实现,在这些方法中都可以通过JoinPoint实例来获得方法执行的上下文信息,参数信息。需要注意AfterReturning和AfterThrowing,After三种不同Advice的执行顺序。

有了spring框架和aspectj以及cglib的支持,我们只需要实现上面两个类就可以使用spring aop的功能了,下面我们看下如何在spring的配置文件中配置spring aop。

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <aop:aspectj-autoproxy />
    <context:component-scan base-package="cn.outofmemory" /> 
</beans>

注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加<aop:aspectj-autoproxy/>就可以了。<context:component-scan/>节点用来指定自动扫描bean的命名空间

最后我们要测试下aop的效果,需要新建一个App类作为程序的入口类。

package cn.outofmemory.spring_aop_aspect;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
    PersonService personService = appContext.getBean(PersonService.class);
    String personName = "Jim";
    personService.addPerson(personName);
    personService.deletePerson(personName);
    personService.editPerson(personName);
    ((ClassPathXmlApplicationContext)appContext).close();
    }
}

这个类中我们初始化了ApplicationContext,然后从中得到PersonService的实例,并执行其addPerson,deletePerson,editPerson方法,最后关闭ApplicationContext。

其执行结果如下:

before aspect executing
around start..
add person Jim
after aspect executed
around end
afterReturning executed, return result is null
-------------------------------------
before aspect executing
around start..
delete person Jim
after aspect executed
around end
afterReturning executed, return result is null
----------------------------------------
before aspect executing
around start..
edit person Jim
after aspect executed
error in around
error:java.lang.RuntimeException: edit person throw exception
Exception in thread ...

从上面执行结果可以看到我们要执行的Before,around,after以及around,afterReturning,afterThrowing都正常的执行了。

最后给出此示例项目的完整代码:spring-aop-aspect.zip

Spring AspectJ AOP 完整示例的更多相关文章

  1. Spring学习总结(六)——Spring整合MyBatis完整示例

    为了梳理前面学习的内容<Spring整合MyBatis(Maven+MySQL)一>与<Spring整合MyBatis(Maven+MySQL)二>,做一个完整的示例完成一个简 ...

  2. Spring集成MyBatis完整示例

    该文详细的通过Spring IOC.MyBatis.Servlet.Maven及Spring整合MyBatis的等技术完成一个简单的图书管理功能,实现图书列表.删除.多删除.编辑.新增功能.梳理前面学 ...

  3. Spring操作指南-AOP基本示例(基于注解)

  4. Spring操作指南-AOP基本示例(基于XML)

  5. Spring 3 AOP 概念及完整示例

    AOP概念 AOP(Aspect Oriented Programming),即面向切面编程(也叫面向方面编程,面向方法编程).其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能.像 ...

  6. Spring的AOP AspectJ切入点语法详解(转)

    一.Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示 ...

  7. spring(二) AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  8. 10 Spring框架 AOP (三) Spring对AspectJ的整合

    上两节我们讲了Spring对AOP的实现,但是在我们的开发中我们不太使用Spring自身的对AOP的实现,而是使用AspectJ,AspectJ是一个面向切面的框架,它扩展了Java语言.Aspect ...

  9. Spring IOC 和Aspectj AOP

    1.Aspectj AOP 是一套独立的AOP 解决方案,不仅限于java应用,不依赖其他方案,属于编译时增强,有自己单独的编译器.Spring AOP 是基于Spring 容器的的AOP解决方式,属 ...

随机推荐

  1. Oracle基础 索引

    一.索引 索引是一种快速访问数据的途径,可提高数据库性能.索引使数据库程序无须对整个表进行扫描,就可以在其中找到所需的数据,就像书的目录,可以快速查找所需的信息,无须阅读整本书. (一)索引的分类 逻 ...

  2. Architects Must Be Hands On

     Architects Must Be Hands On John Davies A good ARCHiTECT SHould lEAd By ExAMplE. He (or she) shoul ...

  3. keycode值大全

    13 我们只知道13是回车,主要是其他的也不是很常用,所以不用记. keycode 8 = BackSpace BackSpace   keycode 9 = Tab Tab   keycode 12 ...

  4. ubuntu+tomcat,多环境、自动化部署脚本,git+maven+tomcat+ubuntu

     1.切换到/opt/code目录,没有利用mkdir code创建code目录,新建deploy.sh 脚本文件,内容如下 projectName=""; #默认tomcat目录 ...

  5. 手写 jQuery 框架

    1.测试页面; <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  6. react-native 项目实战 -- 新闻客户端(4) -- 请求网络数据

    1.Home.js /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Te ...

  7. python 搭建环境

    直接命令行里面 1.进入相应的目录 ,然后python,然后python setup.py 2.或者直接python C:\Python27\Lib\site-packages\xlrd-0.9.3\ ...

  8. Nginx:处理HTTP请求

    参考资料<深入理解Nginx>(陶辉) 处理HTTP请求 接着上一次的内容,本次将说明HTTP框架是如何召集负责具体功能的各HTTP模块合作处理请求的. 在http://www.cnblo ...

  9. 通过rinetd实现端口转发,同时访问阿里云RDS的内外网

    配置方法如下: 1 wget http://www.boutell.com/rinetd/http/rinetd.tar.gz&&tar -xvf rinetd.tar.gz& ...

  10. C#中的里氏替换原则

    里氏转换原则 子类可以赋值给父类对象 父类对象可以强制转化为对应的子类对象 里氏替换原则直观理解就是"子类是父类",反过来就说不通了. 就像男人是人对的,但人是男人就不对了. 这样 ...