一、spring aop的优缺点
优点:低侵入式设计,耦合性低,维护性高。
缺点:采用反射生成代理对象,性能上有瓶颈;织入增强处理都是同步的单一线程,总是在方法返回之前进行。
二、业务场景分析
对一般的业务场景,我们采用aop是可以的。但是如果我们的织入处理很复杂,而且与方法的返回无关。比如复杂日志的记录,这时候我们考虑异步方式去完成代理方法的增强处理。大型的系统,可以采用aop+MQ,自己维护一个消息队列系统,在对方法进行拦截后,只需发送消息到MQ系统,告诉另一个业务系统需要做什么。现在的业务场景是,下游客户调用我们API,我们API调用上游API,需要将调用情况记录数据库进行计费。这里,通过一个单例队列来存放“消息”,并开启一个线程轮询从队列取“消息”,再进行“消费”处理。
三、代码实践
这里采用AspectJ的方式,完成aop动态代理:
存放消息的队列:
/**
* 存放消息的队列
* 这里采用无界队列LinkedBlockingQueue,由于存的对象可能使上游计费对象,
* 也可能是下游计费对象,这里用泛型
* @author robert
*
* @param <T>
*/
@Component
public class ChargingQueue<T> {
private BlockingQueue<T> chargeQueue = new LinkedBlockingQueue<T>();
public void add(T t) {
chargeQueue.add(t);
}
public T poll() throws InterruptedException {
return chargeQueue.poll(1, TimeUnit.SECONDS);
}
}
切点类:
/**
*
* @ClassName: ChargeAspect
* @Description: 切点类
* @author robert
* @date 2017-7-6
*
*/
@Aspect
@Component
public class ChargeAspect {
@Autowired
private ChargingQueue chargingQueue;
// 本地异常日志记录对象
private static final Logger logger = Logger.getLogger(ChargeAspect.class);
// 上游计费切点
@Pointcut("@annotation(com.roman.api.aop.async.charge.UpStreamChargingLog)")
public void upStreamCharging() {
}
// 下游计费切点
@Pointcut("@annotation(com.roman.api.aop.async.charge.DownStreamChargingLog)")
public void downStreamCharging(