spring aop 【实用】【原创】
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
spring aop 对于很多人来说都很熟悉,将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
这几天刚好公司要做操作记录功能,自己也把aop重新温习了一下,自己有一点小心得分享一下。
如何使用Spring AOP
可以通过xml文件来进行
这也是我最常用的方式
<aop:aspectj-autoproxy />
<!-- 定义切面 -->
<aop:config>
<aop:aspect ref="aspectTest">
<aop:pointcut id="log" expression="execution(* com.XXX.service.*.*(..))"/>
<aop:after method="after" pointcut-ref="log"/>
<aop:before method="before" pointcut-ref="log"/>
</aop:aspect>
<aop:aspect ref="logAspect">//指定切面类
<aop:pointcut id="log" expression="@annotation(com.XXX.service.aop.SystemLog)"/>//注解方式
<aop:after-returning method="orderOperate" pointcut-ref="log"/>//操作完成后返回,执行方法logAspect类的orderOperate方法
aop:方式有
我就不一一介绍 了,网上很多介绍,百度一下一大把
</aop:aspect>
</aop:config>
expression有几种方式 ,大家可以参考一下
通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring
在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
我最常用的是@annotation
那得自己写个注解,我的注解是这样子的
import java.lang.annotation.*;
/**
*自定义注解 拦截service
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
String value() default "";
}
然后就可以使用@SystemLog这注解了
那我所用到的地方是
@RequestMapping(value = "update/{orderId}/{status}",produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@SystemLog("workerUpdateStatus")
public ModelResult acceptOrder(@RequestHeader String token,
@PathVariable("orderId") Long orderId,
@PathVariable("status") Integer status){
Long id = wUserTokenService.checkToken(token).getId();
orderService.workerUpdateOrderStatus(orderId,id,status);
return ModelResult.getSuccessResult("");
}
这样子就可以直接到切面类 logAspect ,
/**
* log 切面类
*/
@Component
public class LogAspect {
//订单操作
public void orderOperate(JoinPoint joinPoint) throws Exception {
String description = getLogDescription(joinPoint);//获取注解值
Object[] args = joinPoint.getArgs();//获取方法参数
System.out.println(description);
System.out.println(Arrays.toString(args));
//todo 你想做的事情
}
//获取@SystemLog("test")的test
public static String getLogDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description = method.getAnnotation(SystemLog.class).value();
break;
}
}
}
return description;
}
这是XML注解方式,还有直接用@Aspect方式定义切面等等,都是可以的。
今天时间比较赶,朋友催着回家,先就写到这里吧,欢迎大家多多指教,谢谢