转载请注明出处:http://blog.csdn.net/l1028386804/article/details/49744721
这里我们用一个完整的例子演示spring aspectj aop的使用。
首先新建一个maven项目,在项目的pom.xml中添加spring aop相关的依赖项:
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。
注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加
就可以了。
最后我们要测试下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都正常的执行了。