关于Spring AOP的一点使用(纯注解)

一、导包

需要引入jar包:aspectjweaver.jar aspectjrt.jar(maven方式可以直接复制maven库的引用地址)
目录结构

二、后台代码

@Aspect
@Component
public class Aopconfig {
	@Autowired
	private HttpSession session;
		
	@Pointcut("execution(* com.*.service..save*(..)))")
	public void pointTwo(){}
	
  @Before("pointOne()")
  public void doExecutionAspect(){   
  System.out.println("前置通知");
  }
  @AfterThrowing("pointTwo()")
  public void dow(){
	  System.out.println("异常");
  }
@AfterReturning("pointTwo()")
  public void dd(JoinPoint joinPoint) {
  System.out.println("后置通知");
}
//  /**
//   * 环绕通知:目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码
//   * @return 
//   */
//  @Around(value="execution(* com.*.service..save*(..))")
//  public Object aroundMethod(ProceedingJoinPoint jp){
//      String methodName = jp.getSignature().getName();
//      Object result = null;
//      try {
//          System.out.println("【环绕通知中的--->前置通知】:the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));
//          //执行目标方法
//          result = jp.proceed();
//          System.out.println("【环绕通知中的--->返回通知】:the method 【" + methodName + "】 ends with " + result);
//      } catch (Throwable e) {
//          System.out.println("【环绕通知中的--->异常通知】:the method 【" + methodName + "】 occurs exception " + e);
//      }
//      
//      System.out.println("【环绕通知中的--->后置通知】:-----------------end.----------------------");
//      return result;
//  }

三、用法

@Aspect
这是必须要的,告诉Spring这个类是执行AOP的类。如果你是用纯注解的方式,那么这个是必须的。
@Component
这是把普通pojo实例化到spring容器中,相当于配置文件中的。如果不加入,Spring 会无法将切面类实例化。
@Autowired
对类成员变量、方法及构造函数进行标注,完成自动装配的工作,消除 set ,get方法,不用在xml引用的标签。
@Pointcut(“execution(* com..service…save(…)))”)
@Pointcut主要是告诉AOP拦截的方式,execution是如何进行拦截。
public void pointTwo(){}这是个poincut的签名,方便后面四个注解使用。

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) 

1)括号中各个pattern分别表示

 - 修饰符匹配(modifier-pattern?)
 -  返回值匹配(ret-type-pattern)可以为*表示任何返回值,全路径的类名等
 - 类路径匹配(declaring-type-pattern?)
 - 方法名匹配(name-pattern)可以指定方法名 或者 *代表所有,
 - set* 代表以set开头的所有方法
 - 参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String)
 - 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数
 - 异常类型匹配(throws-pattern?) 其中后面跟着“?”的是可选项

2)使用方法的配置

1)execution(* *(..))  
//表示匹配所有方法  
2)execution(public * com. abc.service.UserService.*(..))  
//表示匹配com.abc.server.UserService中所有的公有方法  
3)execution(* com.abc.server..*.*(..))  
//表示匹配com.abc.server包及其子包下的所有方法

四、注解方式使用

也可以将pointcut表达式放在一个类里

package com.abc.aop;
import org.aspectj.lang.annotation.*;

public class Pointcuts {
@Pointcut("execution(* *Message(..))")
public void logMessage(){}

@Pointcut("execution(* *Attachment(..))")
public void logAttachment(){}

@Pointcut("execution(* *Service.*(..))")
public void auth(){}
}

在使用上面定义Pointcut时,指定完整的类名加上Pointcut签名就可以了,如:

package com.abc.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class LogBeforeAdvice {
@Before("com.abv.aop.Pointcuts.logMessage()")
public void before(JoinPoint joinPoint) {
System.out.println("Logging before " + joinPoint.getSignature().getName());
}
}

@AfterThrowing 是异常通知,拦截异常信息。
@Around 是环绕通知,目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码。JoinPoint joinPoint可用。
**@Before 是前置通知,目标方法执行之前执行以下方法体的内容 **
@After 是后置通知,在所拦截方法执行之后执行一段逻辑,不管是否发生异常。
@AfterReturning 是返回通知,目标方法正常执行完毕时执行以下代码。JoinPoint joinPoint可用。
XML配置

<!-- 激活组件扫描功能,在包cn.ysh.studio.spring.aop及其子包下面自动扫描通过注解配置的组件 -->
	<context:component-scan base-package="扫描的包"/>
	<!-- 激活自动代理功能-->
	<aop:aspectj-autoproxy proxy-target-class="true"/>

最初我是用@around这个方法,但是拦截之后,无法正常执行方法,这个我到现在都没有解决,我换成了@AfterReturning。

提示:如果你要获得登录的ID,无法再dd( HttpSession session),会报错
@Autowired private HttpSession session;
最后如果你还想了解如何使用,建议你搜索JoinPoint、PropertyUtils和Method如何使用,两者可以帮住你拦截执行这个方法传出的值。例如:

Object[] args=joinPoint.getArgs();
//输出拦截的类以及所在的目录位置。
System.out.println(joinPoint.getSignature().getDeclaringTypeName().toString());
//获取ID,同理可以定义不同String获取实体类的值,这是个笨方法,更好的方法是通过反射,遍历类的每个字段,动态生成日志语句,目前我没有实现。
Long id=Long.valueOf(PropertyUtils.getProperty(object, "id").toString());

如果项目的包名不规范,可以这样子写

execution(* com.*.service..save*(..)))

或者

execution(* com.*.*.service..save*(..)))

在你想适配的service包前有几层结果就用几个.*代替,最后要记得方法如果没有指定方法则*.*结尾。
PS:不完全原创,参考部分博客的写法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值