spring注解实现AOP

利用spring实现AOP有两种方式:注解和xml文件定义。前者比较灵活,利于维护。一个小例子:

一、接口PersonService

package com.aoptest.service;

public interface PersonService

{

public void save(String name);

public void update(String name,Integer id);

public String getPersonName();

}

二、接口的实现类PersonServiceBean

package com.aoptest.service.impl;

import com.aoptest.service.PersonService;

public class PersonServiceBean implements PersonService

{

@Override

public String getPersonName()

{

System.out.println("我是getPersonName()方法。。。");

return "返回结果";

}

@Override

public void save(String name)

{

System.out.println("我是save()方法。。。");

throw new RuntimeException("异常了。。");

}

@Override

public void update(String name, Integer id)

{

System.out.println("我是update()方法。。。");

}

}

三、spring配置文件applicationContext.xml

<?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:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:aspectj-autoproxy />

<bean id="myInterceptor" class="com.aoptest.service.MyInterceptor" />

<bean id="personService" class="com.aoptest.service.impl.PersonServiceBean"></bean>

</beans>

ps:

1、红色部分是引入springAOP的命名空间

2、绿色部分必须要有,声明需要AOP操作

3、蓝色部分是做测试时用

四、切面部分MyInterceptor

/**

* 切面

*/

@Aspect //声明此类为一个切面

public class MyInterceptor

{

@Pointcut("execution(* com.aoptest.service..*.*(..))")//声明一个切入点,可以拦截具体到某个方法,即在执行此方法之前、之后、最终、异常……时可以执行的其他业务方法(通知advice);括号内的意思是:拦截某个方法,返回值是所有类型(第一个*),com.aoptest.service包及其子包下的所有类(..*),类下所有的方法(第三个.*),返回值任意(内部嵌套括号(..))

//@Pointcut("execution(* com.aoptest.service.impl.PersonServiceBean.*(..))")//同上,两种都可以

private void anyMethod(){}//声明一个切入点

@Before("anyMethod() && args(name)")//声明前置通知

public void doBefore(String name){

System.out.println("前置通知");

System.out.println("---"+name+"---");//可以得到参数值,此时args(name)限制条件限定了"execution(* com.aoptest.service..*.*(..))"中只拦截参数个数只有1个且类型为String的方法,而不是所有方法(该属性在当前拦截中适用,即前置通知适用)

}

@AfterReturning(pointcut="anyMethod()",returning="result")//声明后置通知

public void doAfterReturning(String result){

System.out.println("后置通知");

System.out.println("---"+result+"---");//返回结果,同上

}

@AfterThrowing(pointcut="anyMethod()",throwing="e")//声明例外通知

public void doAfterThrowing(Exception e){

System.out.println("例外通知");

System.out.println(e.getMessage());//获取异常信息,同上

}

@After("anyMethod()")//声明最终通知

public void doAfter(){

System.out.println("最终通知");

}

@Around("anyMethod()")//声明环绕通知

public Object doAround(ProceedingJoinPoint pjp)throws Throwable

{

System.out.println("进入方法---环绕通知");

Object o = pjp.proceed();

System.out.println("退出方法---环绕通知");

return o;

}

}

五、测试部分

public class SpringAopTest

{

@Test public void interceptorTest()

{

ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

PersonService personService = (PersonService)cxt.getBean("personService");

personService.save("xx");

String result=personService.getPersonName();

System.out.println(result);

}

}

需要导入的包

spring注解实现AOP

说明

1.pointcut语法

execution ——for matching method execution join points

within —— 指定连接点所在的Java类型。

this ——bean reference (Spring AOP proxy) is an instance of the given type

<wbr> target —— the target object (application object being proxied) is an instance of the given type</wbr>

args —— 指定传入到连接点的参数

@target —— the class of the executing object has an annotation of the given type

@args —— the runtime type of the actual arguments passed have annotations of the given type(s)

@within —— limits matching to join points within types that have the given annotation

@annotation —— the subject of the join point (method being executed in Spring AOP) has the given annotation

组合pointcut表达式

可以使用 && 、|| 、! 组合pointcut表达式。

execution格式

execution(

可见性(可选) —— 使用public、protected、private指定可见性。也可以为*,表示任意可见性

返回值类型(必须) —— 指定返回值类型

声明类型(可选)—— <wbr>java包</wbr>

方法名(参数模式)(必须) —— 方法名称,和方法接收的参数<wbr></wbr>

异常模式(可选) —— 指定方法签名中是否存在异常类型

)

在pointcut表达式中可以使用 * 、.. 、 +等通配符。

* :表示若干字符(排除 . 在外)

.. :表示若干字符(包括 . 在内)

+ :表示子类 ,比如Info+ 表示Info类及其子类

2.定义Advice
advice在关联的pointcut表达式的方法运行前(before)、运行后(after)、运行前后(around)执行。
Before Advice:
使用@Before定义Before Advice。
参数:value :绑定到Advice的Pointcut表达式
After returning advice
在匹配的方法执行之后运行该Adivce。使用@AfterReturning进行注释。
参数:value、pointcut:绑定到Advice的Pointcut表达式
returning:String类型,将方法的返回值绑定到Advice的参数名上。
After throwing advice
在pointcut匹配的方法抛出异常后,执行pointcut关联的Advice。使用@AfterThrowing进行注解。
参数:value、pointcut:绑定到Advice的Pointcut表达式
throwing:String类型,将抛出的异常绑定到Advice的参数上。
After advice
使用After进行注解。
参数:value :绑定到Advice的Pointcut表达式
3.参数
<wbr>使用JoinPoint</wbr>
可以在Advice中的第一个参数中定义org.aspectj.lang.JoinPoint类型的参数(在around Advice中使用ProceedingJoinPoint类型的参数)
java.lang.Object[] getArgs() <wbr>—— returns the method arguments</wbr>
Signature getSignature() <wbr>—— <wbr>returns a description of the method that is being advised</wbr></wbr>
java.lang.Object getTarget() <wbr>—— returns the target object<wbr></wbr></wbr>
java.lang.Object getThis()<wbr>—— returns the proxy object</wbr>
pointcut中使用args传递参数