这个例子非常的简单,下面是实体类
- package test;
- /**
- *
- * @author neu_20063500
- *
- */
- public class HelloWorld {
- public void sayHello(String helloworld) {
- System.out.println(helloworld);
- throw new RuntimeException();
- //这个异常是拿来测试,可有可无
- }
- }
package test;
/**
*
* @author neu_20063500
*
*/
public class HelloWorld {
public void sayHello(String helloworld) {
System.out.println(helloworld);
throw new RuntimeException();
//这个异常是拿来测试,可有可无
}
}
想使用AOP去处理这个sayHello方法
那么我们定义切面
- package test;
- 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;
- /**
- *
- * @author neu_20063500
- *
- */
- @Aspect
- public class AspectS {
- // execution最常用,可以通过 & || !进行切入点表达式的连接
- // 可是是表达式,可以通过切入点标识重用表达式
- @Pointcut ( "execution(public void test.HelloWorld.sayHello(String))" )
- public void helloworld() {
- }
- @Before ( "execution(public void test.HelloWorld.sayHello(String))" )
- public void beforeSayHello() {
- System.out.println("before sayHello" );
- }
- @After ( "helloworld()" )
- public void afterSayHello() {
- System.out.println("after sayHello" );
- }
- @AfterThrowing ( "test.AspectS.helloworld()" )
- public void exceptionSayHello() {
- System.out.println("throw runtime exception" );
- }
- @AfterReturning ( "test.AspectS.helloworld()" )
- public void returnSayHello() {
- System.out.println("method has returned" );
- }
- @Around ( "test.AspectS.helloworld()" )
- public Object aroundSayHello(ProceedingJoinPoint pjp) {
- Object obj = null ;
- try {
- System.out.println("around start" );
- obj = pjp.proceed();
- System.out.println("around end" );
- } catch (Throwable e) {
- e.printStackTrace();
- }
- return obj;
- }
- /*
- 任意公共方法的执行:
- execution(public * *(..))
- 任何一个以“set”开始的方法的执行:
- execution(* set*(..))
- AccountService 接口的任意方法的执行:
- execution(* com.xyz.service.AccountService.*(..))
- 定义在service包里的任意方法的执行:
- execution(* com.xyz.service.*.*(..))
- 定义在service包或者子包里的任意方法的执行:
- execution(* com.xyz.service..*.*(..))
- 在service包里的任意连接点(在Spring AOP中只是方法执行) :
- within(com.xyz.service.*)
- 在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :
- within(com.xyz.service..*)
- 实现了 AccountService 接口的代理对象的任意连接点(在Spring AOP中只是方法执 行) :
- this(com.xyz.service.AccountService)
- 'this'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得代理对象可以在通知 体内访问到的部分。
- 实现 了 AccountService 接口的目标对象的任意连接点(在Spring AOP中只是方法执行) :
- target(com.xyz.service.AccountService)
- 'target'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得目标对象可以在 通知体内访问到的部分。
- 任何一个只接受 一个参数,且在运行时传入的参数实现了 Serializable 接口的连接点 (在Spring AOP中只是方法执行)
- args(java.io.Serializable)
- 'args'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得方法参数可以在通知 体内访问到的部分。
- 请注意在例子中给出 的切入点不同于 execution(* *(java.io.Serializable)): args只有在动态运行时候传入参数是可序列化的 (Serializable)才匹配,而execution 在传入参数的签名声明的类型实现了 Serializable 接口时候匹配。
- 有一 个 @Transactional 注解的目标对象中的任意连接点(在Spring AOP中只是方法执行)
- @target(org.springframework.transaction.annotation.Transactional)
- '@target' 也可以在binding form中使用:请常见以下讨论通知的章节中关于如何使得 annotation对象可以在通知体内访问到的部分。
- 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点(在Spring AOP中只是方法执 行)
- @within(org.springframework.transaction.annotation.Transactional)
- '@within'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得 annotation对象可以在通知体内访问到的部分。
- 任何一个执行的方法有一个 @Transactional annotation的连接点(在Spring AOP中只 是方法执行)
- @annotation(org.springframework.transaction.annotation.Transactional)
- '@annotation' 也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得 annotation对象可以在通知体内访问到的部分。
- 任何一个接受一个参数,并且传入的参数在运行时的类型实现了 @Classified annotation的连接点 (在Spring AOP中只是方法执行)
- @args(com.xyz.security.Classified)
- '@args'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得 annotation对象可以在通知体内访问到的部分。
- */
- }
package test;
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;
/**
*
* @author neu_20063500
*
*/
@Aspect
public class AspectS {
// execution最常用,可以通过 & || !进行切入点表达式的连接
// 可是是表达式,可以通过切入点标识重用表达式
@Pointcut("execution(public void test.HelloWorld.sayHello(String))")
public void helloworld() {
}
@Before("execution(public void test.HelloWorld.sayHello(String))")
public void beforeSayHello() {
System.out.println("before sayHello");
}
@After("helloworld()")
public void afterSayHello() {
System.out.println("after sayHello");
}
@AfterThrowing("test.AspectS.helloworld()")
public void exceptionSayHello() {
System.out.println("throw runtime exception");
}
@AfterReturning("test.AspectS.helloworld()")
public void returnSayHello() {
System.out.println("method has returned");
}
@Around("test.AspectS.helloworld()")
public Object aroundSayHello(ProceedingJoinPoint pjp) {
Object obj = null;
try {
System.out.println("around start");
obj = pjp.proceed();
System.out.println("around end");
} catch (Throwable e) {
e.printStackTrace();
}
return obj;
}
/*
任意公共方法的执行:
execution(public * *(..))
任何一个以“set”开始的方法的执行:
execution(* set*(..))
AccountService 接口的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))
定义在service包或者子包里的任意方法的执行:
execution(* com.xyz.service..*.*(..))
在service包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service.*)
在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service..*)
实现了 AccountService 接口的代理对象的任意连接点(在Spring AOP中只是方法执行) :
this(com.xyz.service.AccountService)
'this'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得代理对象可以在通知体内访问到的部分。
实现了 AccountService 接口的目标对象的任意连接点(在Spring AOP中只是方法执行) :
target(com.xyz.service.AccountService)
'target'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得目标对象可以在通知体内访问到的部分。
任何一个只接受一个参数,且在运行时传入的参数实现了 Serializable 接口的连接点 (在Spring AOP中只是方法执行)
args(java.io.Serializable)
'args'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得方法参数可以在通知体内访问到的部分。
请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)): args只有在动态运行时候传入参数是可序列化的(Serializable)才匹配,而execution 在传入参数的签名声明的类型实现了 Serializable 接口时候匹配。
有一个 @Transactional 注解的目标对象中的任意连接点(在Spring AOP中只是方法执行)
@target(org.springframework.transaction.annotation.Transactional)
'@target' 也可以在binding form中使用:请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。
任何一个目标对象声明的类型有一个 @Transactional 注解的连接点(在Spring AOP中只是方法执行)
@within(org.springframework.transaction.annotation.Transactional)
'@within'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。
任何一个执行的方法有一个 @Transactional annotation的连接点(在Spring AOP中只是方法执行)
@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation' 也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。
任何一个接受一个参数,并且传入的参数在运行时的类型实现了 @Classified annotation的连接点(在Spring AOP中只是方法执行)
@args(com.xyz.security.Classified)
'@args'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。
*/
}
然后定义配置文件,注意将切面对象和实体对象交给Spring管理:
- <? 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:context = "http://www.springframework.org/schema/context"
- xmlns:aop = "http://www.springframework.org/schema/aop" xmlns:tx = "http://www.springframework.org/schema/tx"
- xsi:schemaLocation ="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- < context:annotation-config />
- < aop:aspectj-autoproxy />
- < bean id = "aspects" class = "test.AspectS" > </ bean >
- < bean id = "helloworld" class = "test.HelloWorld" > </ bean >
- </ beans >
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /> <aop:aspectj-autoproxy /> <bean id="aspects" class="test.AspectS"></bean> <bean id="helloworld" class="test.HelloWorld"></bean> </beans>
然后使用客户端调用:
- package test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Client {
- public static void main(String[] args) {
- ApplicationContext cx = new ClassPathXmlApplicationContext(
- "applicationContext.xml" );
- HelloWorld bean = (HelloWorld)cx.getBean("helloworld" );
- bean.sayHello("hello world" );
- }
- }
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext cx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
HelloWorld bean = (HelloWorld)cx.getBean("helloworld");
bean.sayHello("hello world");
}
}
当sayHello没有抛出异常时,执行结果是:
- before sayHello
- around start
- hello world
- after sayHello
- method has returned
- around end
before sayHello
around start
hello world
after sayHello
method has returned
around end
当sayHello执行抛出异常时候,执行结果是
- around start
- hello world
- after sayHello
- throw runtime exception
around start
hello world
after sayHello
throw runtime exception
给出一个比较典型和常用的切点:
- package test;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class SystemArchitecture {
- /**
- * A join point is in the web layer if the method is defined in a type in
- * the com.xyz.someapp.web package or any sub-package under that.
- */
- @Pointcut ( "within(com.xyz.someapp.web..*)" )
- public void inWebLayer() {
- }
- /**
- * A join point is in the service layer if the method is defined in a type
- * in the com.xyz.someapp.service package or any sub-package under that.
- */
- @Pointcut ( "within(com.xyz.someapp.service..*)" )
- public void inServiceLayer() {
- }
- /**
- * A join point is in the data access layer if the method is defined in a
- * type in the com.xyz.someapp.dao package or any sub-package under that.
- */
- @Pointcut ( "within(com.xyz.someapp.dao..*)" )
- public void inDataAccessLayer() {
- }
- /**
- * A business service is the execution of any method defined on a service
- * interface. This definition assumes that interfaces are placed in the
- * "service" package, and that implementation types are in sub-packages.
- *
- * If you group service interfaces by functional area (for example, in
- * packages com.xyz.someapp.abc.service and com.xyz.def.service) then the
- * pointcut expression "execution(* com.xyz.someapp..service.*.*(..))" could
- * be used instead.
- */
- @Pointcut ( "execution(* com.xyz.someapp.service.*.*(..))" )
- public void businessService() {
- }
- /**
- * A data access operation is the execution of any method defined on a dao
- * interface. This definition assumes that interfaces are placed in the
- * "dao" package, and that implementation types are in sub-packages.
- */
- @Pointcut ( "execution(* com.xyz.someapp.dao.*.*(..))" )
- public void dataAccessOperation() {
- }
- }
-