Spring AspectJ AOP 简单示例

来源:互联网 发布:巨石监控分析软件 编辑:程序博客网 时间:2024/05/18 00:57

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

这里我们用一个完整的例子演示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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.bwu.aop</groupId>    <artifactId>bwu-aop-demo</artifactId>    <name>bwu-aop-demo</name>    <version>1.0-SNAPSHOT</version>    <description>demo for learning AOP</description>    <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 com.bwu.aop.spring.aspect;import org.springframework.stereotype.Service;@Servicepublic 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 com.bwu.aop.spring.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@Aspectpublic class SimpleAspect {    @Pointcut("execution(* com.bwu.aop.spring.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("after Returning 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 />    <!-- Use context:component-scan will auto register the spring bean with @Componet, @Service, ... -->    <!--     <context:component-scan base-package="com.bwu.aop" />     -->     <bean id="personService" class="com.bwu.aop.spring.aspect.PersonService"/>    <bean id="simpleAspect" class="com.bwu.aop.spring.aspect.SimpleAspect"/></beans>

注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加就可以了。节点用来指定自动扫描bean的命名空间。

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

package com.bwu.aop.spring.aspect;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringAOPMain {    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 executingaround start..add person Jimafter aspect executedaround endafter Returning executed, return result is nullbefore aspect executingaround start..delete person Jimafter aspect executedaround endafter Returning executed, return result is nullbefore aspect executingaround start..edit person Jimafter aspect executederror in arounderror:java.lang.RuntimeException: edit person throw exceptionException in thread "main" java.lang.RuntimeException: edit person throw exception ... ...
0 0