Spring 框架 AOP的原理及应用

AOP 原理:

第一.将复杂的需求分解出不同的方面,将公共功能集中解决。

第二、采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能

所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态添加功能的技术

AOP:

面向切面编程,相对于OOP切面编程

Spring 的AOP为了解耦,AOP可以让一组类共享相同的行为

Spring 支持Aspect声明的注解式切面编程

 

 

下面的代码示例:

为了解决在执行某个方法时,需要切换数据库

@Aspect
@Component
public class DataSourceAspect {
    @Before("execution(* cn.com.citydo.web.mapper.oracle.ExecuteSqlFromOracleMapper.execute(..))")
    public void setSecondaryDataSource(JoinPoint point) {
        DatabaseContextHolder.setDatabaseType(DatabaseType.secondaryDb);
    }

    @After("execution(* cn.com.citydo.web.mapper.oracle.ExecuteSqlFromOracleMapper.execute(..))")
    public void setPrimaryDataSource(JoinPoint point) {
        DatabaseContextHolder.setDatabaseType(DatabaseType.primaryDb);
    }
}

最常见的切面日志配置

package cn.com.citydo.datawindow.config;

import cn.com.citydo.datawindow.dto.base.BaseResponse;
import cn.com.citydo.datawindow.util.annotation.log.LogAnnotation;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 切面日志配置
 *
 * @author yss
 */
@Slf4j
@Aspect
@Component
public class ControllerAspect {

	/**
	 * 切面环绕写入方法名
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(logAnnotation)")
	public Object interceptor(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
		long start = System.currentTimeMillis();

		// 类路径
		String className = joinPoint.getSignature().getDeclaringTypeName();

		// 方法名
		String methodName = joinPoint.getSignature().getName();

		StringBuilder sb = new StringBuilder();
		sb.append(className).append(".").append(methodName);

		log.info("开始调用方法:{}", sb);
		log.info("请求参数 : " + JSON.toJSON(joinPoint.getArgs()));

		// 后置通知获取返回结果集,proceed()方法只可调一次,否则会重复执行业务服务
		Object responseObj = joinPoint.proceed();

		// 计算服务端接口耗时,单位毫秒
		long costTime = System.currentTimeMillis() - start;

		// 响应结果为BaseResponse时添加方法名
		BaseResponse response;
		if (responseObj instanceof BaseResponse) {
			response = (BaseResponse) responseObj;
			response.setAction(methodName);
			response.setCostTime(costTime);
		} else {
			return responseObj;
		}

		// 后置通知记录返回对象
		log.info("结束调用方法:{}, 耗时:{}ms", sb, costTime);
		log.info("调用结果 : " + JSON.toJSON(responseObj));

		// 结束切面
		return response;
	}

}

 

1) @Aspect  声明一个切面

2) @Component 让此切面成为spring 容器管理的bean

3) @PointCut 注解声明切点

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值