多次调用AspectJProxyFactory.addAspect(this)是否会导致应用性能下降?
问题描述
我需要拦截外部库中由对象#1动态实例化/获取的对象#2的调用。做法是先拦截对象#1,再为对象#2添加切面,以此统计调用次数、抛出的异常、响应时间等指标。
代码示例如下:
// 我的切面拦截获取对象#2的对象#1,并为对象#2添加切面 Object obj2 = joinPoint.proceed(); AspectJProxyFactory proxyFactory = new AspectJProxyFactory(obj2); proxyFactory.addAspect(this);
由于obj2会被获取数百万次,反复调用proxyFactory.addAspect(this)是否会随时间推移导致应用性能下降?该调用是否具备幂等性、副作用极小?
注:我猜测obj2仅会被实例化一次或几次,之后始终为同一对象,但因这是闭源外部库,我无法确认此情况。
解答
- 性能影响:如果每次获取obj2都创建新的
AspectJProxyFactory并生成代理对象,数百万次调用必然带来显著性能损耗——对象实例化、代理类生成(即便有缓存)、字节码操作等步骤会持续占用CPU和内存,长期运行会加剧GC压力,甚至引发内存溢出。 - 幂等性与副作用:这种调用不具备幂等性。若obj2是同一对象,反复为它创建代理会生成多层代理结构,每次实际调用都会经过所有代理层,不仅性能逐步恶化,统计的指标也会重复计算(比如一次真实调用会被多个代理切面多次统计)。另外,若多次对同一代理工厂调用
addAspect(this),会重复添加切面,导致同一方法被多次拦截,直接造成统计数据失真。 - 优化建议:
- 增加一层缓存机制,用
WeakHashMap存储已代理过的obj2实例,避免重复代理:private final WeakHashMap<Object, Object> proxiedObjects = new WeakHashMap<>(); // 切面逻辑中 Object obj2 = joinPoint.proceed(); return proxiedObjects.computeIfAbsent(obj2, key -> { AspectJProxyFactory proxyFactory = new AspectJProxyFactory(key); proxyFactory.addAspect(this); return proxyFactory.getProxy(); }); - 若外部库的obj2是单例或少量实例,缓存能极大降低重复代理的开销;若为大量不同实例,弱引用缓存可避免内存泄漏问题。
- 增加一层缓存机制,用
内容的提问来源于stack exchange,提问作者Joe DiNottra
相关产品推荐
相关产品推荐

