Spring AOP + AspectJ注释示例

在本教程中,我们向您展示如何将AspectJ注释与Spring AOP框架集成在一起。 简单来说,Spring AOP + AspectJ使您可以轻松地拦截方法。

常见的AspectJ注释:

  1. @Before –在方法执行之前运行
  2. @After –在方法返回结果之后运行
  3. @AfterReturning –在方法返回结果之后运行,也拦截返回的结果。
  4. @AfterThrowing –在方法引发异常之后运行
  5. @Around –运行方法执行,结合以上所有三个建议。

注意
对于没有AspectJ支持的Spring AOP,请阅读此内置Spring AOP示例

1.目录结构

请参阅本示例的目录结构。

directory structure of this example

2.项目依赖

要启用AspectJ中,你需要aspectjrt.jar,aspectjweaver.jar弹簧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.四季豆

普通bean,几乎没有方法,后来通过AspectJ注释拦截了它。

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

</beans>

4. AspectJ @之前

在下面的例子中, logBefore()方法将customerBo接口,执行之前被执行addCustomer()方法。

注意
AspectJ“切入点”用于声明将要拦截的方法,您应该参考此Spring AOP切入点指南以获取所支持的切入点表达式的完整列表。

文件: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 @之后

在下面的例子中, logAfter()方法将customerBo接口的执行,之后执行addCustomer()方法。

文件: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

在下面的例子中, logAfterReturning()方法将customerBo接口的执行,之后执行addCustomerReturnValue()方法。 另外,您可以使用“ 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 @AfterReturning

在以下示例中, logAfterThrowing()如果customerBo接口,方法将被执行addCustomerThrowException()方法被抛出异常。

文件: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();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批注。 关于Spring的AspectJ的文章很长。 有关更多说明和示例,请访问下面的参考链接。

反注释还是使用JDK 1.4?
不用担心,AspectJ也支持XML配置,请阅读此Spring AOP + AspectJ XML示例

下载源代码

下载它– Spring3-AOP-AspectJ-Example.zip (8 KB)

参考文献

  1. AspectJ编程指南
  2. Spring AOP + AspectJ参考

翻译自: https://mkyong.com/spring3/spring-aop-aspectj-annotation-example/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值