Spring - AOP - AspectJ annotatio
原文地址:https://mkyong.com/spring3/spring-aop-aspectj-annotation-example/
在本教程中,我们向您展示如何将AspectJ注释与Spring AOP框架集成在一起。
简单来说,Spring AOP + AspectJ使您可以轻松地拦截方法。
常见的AspectJ注释:
- @Before – 在方法执行之前运行
- @After – 方法返回结果后运行
- @AfterReturning – 在方法返回结果之后运行,也将拦截返回的结果。
- @AfterThrowing – 在方法抛出异常后运行
- @Around – 运行方法执行,结合以上所有三个建议
注意:对于没有AspectJ支持的Spring AOP,请阅读。Spring - AOP - Advice
1.目录结构
请参阅本示例的目录结构。
目录结构.png2.项目依赖
要启用AspectJ,您需要aspectjrt.jar,aspectjweaver.jar和spring-aop.jar。
请参阅以下Maven pom.xml文件
从Spring 2.0开始支持AspectJ
此示例使用的是Spring 3,但自Spring 2.0开始支持AspectJ功能。
文件:pom.xml
<project ...>
<properties>
<spring.version>3.0.5.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>
<!-- Spring AOP + AspectJ -->
<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.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
</dependencies>
</project>
3. Spring Beans
package com.mkyong.customer.bo;
public interface CustomerBo {
void addCustomer();
String addCustomerReturnValue();
void addCustomerThrowException() throws Exception;
void addCustomerAround(String name);
}
package com.mkyong.customer.bo.impl;
import com.mkyong.customer.bo.CustomerBo;
public class CustomerBoImpl implements CustomerBo {
public void addCustomer(){
System.out.println("addCustomer() is running ");
}
public String addCustomerReturnValue(){
System.out.println("addCustomerReturnValue() is running ");
return "abc";
}
public void addCustomerThrowException() throws Exception {
System.out.println("addCustomerThrowException() is running ");
throw new Exception("Generic Error");
}
public void addCustomerAround(String name){
System.out.println("addCustomerAround() is running, args : " + name);
}
}
4.启用AspectJ
在Spring配置文件中,放入“ <aop:aspectj-autoproxy />”,然后定义您的Aspect(拦截器)和普通bean。
文件:Spring-Customer.xml
<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"
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 ">
<aop:aspectj-autoproxy />
<bean id="customerBo" class="com.mkyong.customer.bo.impl.CustomerBoImpl" />
<!-- Aspect -->
<bean id="logAspect" class="com.mkyong.aspect.LoggingAspect" />
4. AspectJ @Before
在下面的示例中,将在执行customerBo接口addCustomer()方法之前执行logBefore()方法。
文件:LoggingAspect.java
package com.mkyong.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
运行
CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
customer.addCustomer();
输出
logBefore() is running!
hijacked : addCustomer
******
addCustomer() is running
5. AspectJ @After
在下面的示例中,将在执行customerBo接口addCustomer()方法之后执行logAfter()方法。
文件:LoggingAspect.java
```
package com.mkyong.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
@Aspect
public class LoggingAspect {
@After("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
运行
CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
customer.addCustomer();
输出
addCustomer() is running
logAfter() is running!
hijacked : addCustomer
******
6. AspectJ @AfterReturning
在下面的示例中,将在执行customerBo接口addCustomerReturnValue()方法之后执行logAfterReturning()方法。
另外,您可以使用“returning”属性截取返回的值。
要拦截返回的值,“returning”属性(结果)的值必须与方法参数(结果)相同。
文件:LoggingAspect.java
package com.mkyong.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class LoggingAspect {
@AfterReturning(
pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerReturnValue(..))",
returning= "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("logAfterReturning() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("Method returned value is : " + result);
System.out.println("******");
}
}
运行
CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
customer.addCustomerReturnValue();
输出
addCustomerReturnValue() is running
logAfterReturning() is running!
hijacked : addCustomerReturnValue
Method returned value is : abc
******
7. AspectJ @AfterThrowing
在下面的示例中,如果customerBo接口addCustomerThrowException()方法引发异常,则将执行logAfterThrowing()方法。
文件:LoggingAspect.java
package com.mkyong.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class LoggingAspect {
@AfterThrowing(
pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerThrowException(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("logAfterThrowing() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("Exception : " + error);
System.out.println("******");
}
}
运行
CustomerBo customer = (CustomerBo)appContext.getBean("customerBo");
customer.addCustomerThrowException();
输出
addCustomerThrowException() is running
logAfterThrowing() is running!
hijacked : addCustomerThrowException
Exception : java.lang.Exception: Generic Error
******
Exception in thread "main" java.lang.Exception: Generic Error
//...
8.AspectJ @Around
在下面的示例中,logAround()方法将在customerBo接口,addCustomerAround()方法之前执行,并且您必须定义“ joinPoint.proceed();”以控制拦截器何时应将控件返回到原始addCustomerAround()方法。
文件:LoggingAspect.java
package com.mkyong.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
@Aspect
public class LoggingAspect {
@Around("execution(* com.mkyong.customer.bo.CustomerBo.addCustomerAround(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAround() is running!");
System.out.println("hijacked method : " + joinPoint.getSignature().getName());
System.out.println("hijacked arguments : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Around before is running!");
joinPoint.proceed(); //continue on the intercepted method
System.out.println("Around after is running!");
System.out.println("******");
}
}
运行
CustomerBo customer = (CustomerBo)appContext.getBean("customerBo");
customer.addCustomerAround("mkyong");
输出
logAround() is running!
hijacked method : addCustomerAround
hijacked arguments : [mkyong]
Around before is running!
addCustomerAround() is running, args : mkyong
Around after is running!
******
总结
始终建议使用功耗最低的AsjectJ注解。