Spring AspectJ AOP 完整示例

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

如下是完整的pom.xml:

 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">
	4.0.0

	cn.outofmemory
	spring-aop-aspect
	0.0.1-SNAPSHOT
	jar

	spring-aop-aspect
	http://maven.apache.org
	
		3.1.1.RELEASE
	
	
		
			org.springframework
			spring-core
			${spring.version}
		
		
			org.springframework
			spring-context
			${spring.version}
		
		
			org.springframework
			spring-aop
			${spring.version}
		
		
			org.aspectj
			aspectjrt
			1.6.12
		
		
			org.aspectj
			aspectjweaver
			1.6.12
		
		
			cglib
			cglib
			2.2
		
	

在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"?>
 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">
     />
     base-package="cn.outofmemory" /> 

注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加就可以了。节点用来指定自动扫描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

你可能感兴趣的:(aop,Spring)