Spring AspectJ AOP 完整示例

来源:互联网 发布:php教程视频 百度云 编辑:程序博客网 时间:2024/05/23 16:32

如下是完整的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 classPersonService {


publicvoid addPerson(String personName) {

System.out.println("add person " + personName);

}

publicboolean deletePerson(String personName) {

System.out.println("delete person " + personName) ;

returntrue;

}

publicvoid editPerson(String personName) {

System.out.println("edit person " + personName);

thrownew 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 classSimpleAspect {

@Pointcut("execution(* cn.outofmemory.spring_aop_aspect.*Service*.*(..))")

publicvoid pointCut() {

}


@After("pointCut()")

publicvoid after(JoinPoint joinPoint) {

System.out.println("after aspect executed");

}


@Before("pointCut()")

publicvoid before(JoinPoint joinPoint) {

//如果需要这里可以取出参数进行处理

//Object[] args = joinPoint.getArgs();

System.out.println("before aspect executing");

}


@AfterReturning(pointcut ="pointCut()", returning = "returnVal")

publicvoid afterReturning(JoinPoint joinPoint,Object returnVal) {

System.out.println("afterReturning executed, return result is "

+ returnVal);

}


@Around("pointCut()")

publicvoid 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")

publicvoid 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-scanbase-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 classApp 

{

    publicstatic 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 resultis null

-------------------------------------

before aspect executing

around start..

delete person Jim

after aspect executed

around end

afterReturning executed, return resultis null

----------------------------------------

before aspect executing

around start..

edit person Jim

after aspect executed

error in around

error:java.lang.RuntimeException: edit personthrow exception

Exception in thread ...

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

原创粉丝点击