4.Spring AOP理解

  1. AOP原理
    AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)、Authentication (权限)、Caching(缓存)和调试管理(Debugging)等。

从Spring的角度看,AOP最大的用途就在于提供了事务管理的能力。事务管理就是一个关注点,你的正事就是去访问数据库,而你不想管事务(太烦),所以,Spring在你访问数据库之前,自动帮你开启事务,当你访问数据库结束之后,自动帮你提交/回滚事务!

  1. AOP概念术语
  • 切面(aspect):用来切插业务方法的类。
  • 连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析,如方法的调用或特定的异常被抛出。
  • 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。
  • 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。
  • 引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。
  • 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。
  • AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。
  1. AOP通知类型
  • 前置通知(before advice):在切入点之前执行。
  • 后置通知(after returning advice):在切入点执行完成后,执行通知。
  • 环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。
  • 异常通知(after throwing advice):在切入点抛出异常后,执行通知。
  1. AspectJ相关Jar包

aspectjrt.jar:主要是提供运行时的一些注解,静态方法等等东西,通常我们要使用aspectJ的时候都要使用这个包。
aspectjtools.jar:主要是提供赫赫有名的ajc编译器,可以在编译期将将java文件或者class文件或者aspect文件定义的切面织入到业务代码中。通常这个东西会被封装进各种IDE插件或者自动化插件中。
aspectjweaverjar:主要是提供了一个java agent用于在类加载期间织入切面(Load time weaving)。并且提供了对切面语法的相关处理等基础方法,供ajc使用或者供第三方开发使用。这个包一般我们不需要显式引用,除非需要使用LTW。

5.切面示例

@Aspect
@Component
public class ServiceLogAspect {

	// 设置 Service层切点
	@Pointcut("execution(* com.uaf.nlp.*.service.*.*.*(..))")
	public void serviceAspect() {

	}

	/**
	 * 异常通知 用于拦截service层记录异常日志  
	 * @param joinPoint
	 * @param e
	 * 作者:will
	 * 日期:2016年8月11日下午3:44:45
	 */
	@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
		try {
			String packageName = joinPoint.getTarget().getClass().getPackage().getName();
			String className = joinPoint.getTarget().getClass().getName().substring(packageName.length() + 1) + ".java";
			String methodName = joinPoint.getSignature().getName();

			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			e.printStackTrace(pw);

			Map<String, Object> map = new HashMap<String, Object>();
			map.put("包名", packageName);
			map.put("类名", className);
			map.put("方法", methodName);
			map.put("参数", joinPoint.getArgs());
			map.put("异常信息", sw.toString());

			MyLog4j.textError("[ASPECT]评分模型切面异常日志:{0}", JsonUtil.toJson(map));

		} catch (Exception ex) {
			// 记录本地异常日志
			MyLog4j.textError("切面日志处理异常{0}", LogUtil.ExceptionToString(ex));
		}
	}

	/**
	 * 记录Service层请求参数及返回值
	 * @param joinPoint
	 * @param result
	 * 作者:will
	 * 日期:2016年8月11日下午3:44:53
	 */
	@AfterReturning(pointcut = "serviceAspect()", returning = "result")
	public void afterReturning(JoinPoint joinPoint, Object result) {
		try {
			String packageName = joinPoint.getTarget().getClass().getPackage().getName();
			String className = joinPoint.getTarget().getClass().getName().substring(packageName.length() + 1) + ".java";
			String methodName = joinPoint.getSignature().getName();

			Map<String, Object> map = new HashMap<String, Object>();
			map.put("包名", packageName);
			map.put("类名", className);
			map.put("方法", methodName);
			map.put("参数", joinPoint.getArgs());
			map.put("返回值", result);

			MyLog4j.textInfo("[ASPECT]评分模型切面请求及返回参数日志:{0}", JsonUtil.toJson(map));
		} catch (Exception e) {
			// 记录本地异常日志
			MyLog4j.textError("切面日志处理异常{0}", LogUtil.ExceptionToString(e));
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值