【问题标题】:How efficient is Spring AOP in case of memory consumptionSpring AOP 在内存消耗的情况下效率如何
【发布时间】:2016-05-13 19:02:06
【问题描述】:

在我的宠物项目中,我有一个长期运行的工作,我想向用户显示有关该过程的状态以及它走了多远。因此,我将状态对象从那里推送到 JMS 主题,然后将它们提供给 WS 应用程序以将它们流式传输到有效的客户端。 我在 spring AOP(即@Before,@AfterReturn)中编写了切入点,并调用我的服务将消息发送到主题。现在我想记录服务的状态,而不是在方法启动或在方法内部返回之后。所以我调用了服务(其中注入了 jmsTamplete 并获取了状态对象)。有什么办法可以最小化这些调用,这样我就不能重复服务调用。 这是我的 sudo 代码。

public class Myservice{

UserDao userDao;
LegService legservice;
ProviderDao providerDao;
....
StatusServive statusServie;

//aop will call the same service to send info to JMS topic
fetchandCalculateLeg(){
    // here i called statusServie.senStatus(StatusObject);
    List<Users> = userDao.fetchUserInfo();
    // here i called statusServie.senStatus(StatusObject);
    ....
    loop: #forEachUser
    // here i called statusServie.senStatus(StatusObject);
    someList  = legservice.fecthLegInfoForEachUser();
    // here i called statusServie.senStatus(StatusObject);
    :endloop;
    ....
} }

目前我有 3 个长时间运行的任务,我在每个方法类中都调用相同的。我想尽量减少通话。

编辑1: 我也可以在调用方法上应用 AOP,但是这种情况下的性能如何?如何测量 AOP 性能(在应用程序启动或创建代理对象期间消耗了多少内存)。抱歉问了这么多问题。

【问题讨论】:

  • 您的问题标题似乎没有反映在您的问题中。

标签: java spring-aop


【解决方案1】:

如果你使用 AOP,性能会比这更好,因为它是经过良好测试和优化的框架来执行此类操作。无论如何,您可以通过减去开始和结束时间来检查。

您可以使用您当前的代码和 AOP 实现的代码来检查性能。这将是一项非常有趣的工作。执行以下操作来设置开始和结束时间并减去。

System.currentTimeMillis()

以上语法,以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统并且可能更大。例如,许多操作系统以几十毫秒为单位测量时间。 有关“计算机时间”和协调世界时 (UTC) 之间可能出现的细微差异的讨论,请参见 Date 类的描述。

有许多可用的 AOP 开源框架。

  1. Spring AOP:带有 Spring 框架的 AOP。广告。 Spring Framework 的关键组件之一是面向方面的编程 (AOP) 框架。面向方面的编程需要将程序逻辑分解成不同的部分,称为所谓的关注点。

  2. AspectJ: AspectJ 是 Java 编程语言的面向方面的无缝扩展,兼容 Java 平台,易于学习和使用。 AspectJ 实现了横切关注点的干净模块化,例如:错误检查和处理、同步、上下文相关行为、性能优化、监控和日志记录、调试支持、多对象协议。

  3. AspectWerkz: AspectWerkz 是一个用于 Java 的动态、轻量级和高性能 AOP 框架。 AspectWerkz 既强大又简单,将帮助您轻松地将 AOP 集成到新项目和现有项目中。 AspectWerkz 利用运行时字节码修改在运行时编织您的类。它挂钩并编织由任何类加载器加载的类,除了引导类加载器。它具有丰富且高度正交的连接点模型。方面、建议和介绍是用纯 Java 编写的,您的目标类可以是常规 POJO。您可以添加、删除和重新构建建议以及在运行时交换您的介绍的实施。可以使用 XML 定义文件或使用运行时属性来定义方面。

编辑 1

Spring 还支持 AspectJ。我确实用 AspectJ 1.7.2 对其进行了测试,它没有显示内存泄漏。您可以通过创建大量 bean 然后在一段时间后进行堆转储来在您的应用程序中复制相同的内容,因为垃圾收集需要一些时间,它不是即时的。

根据我的测试。性能不错,没有大量调用。

简单示例在 MKYong 中可用:http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

注意:你应该修改你的问题表现是测量时间和空间。而且,根据您的评论,您似乎在询问更多内存优化或管理方面的内容。此外,您的问题主题与问题不同。

【讨论】:

  • @Praiyush 感谢您的回复,我的问题不在于时间(尽管我现在不太关心),我特别关注这里提到的内存消耗和堆link 幸运的是他们修复了4.2.所以像这样有任何人都知道的担忧。我也在谷歌上搜索以了解更多关于开发人员面临的不同类型的情况(不是全部,只寻找适合我的情况)。因此,如果您对此有更多信息,可以修改您的答案。再次感谢。
  • 谢谢 试试看能不能分享一下内存泄漏的测试结果。
【解决方案2】:

如果你有这么长时间的工作,为什么不把它放到 Spring-Batch 运行时呢?实现自定义阅读器 -> 处理器 -> 编写器,系统将为您完成所有工作。为了显示此类作业执行的详细信息,我创建了这样的 DTO https://gist.github.com/idyoshin/b035317db8c61b1b49ccb8898848171e 和收集器 https://gist.github.com/idyoshin/74ad80841a51e1be62208f3fd58eeb6a。这个实用程序是解决方法,因为我不想将 spring-batch 管理应用程序嵌入到我的主应用程序中。我使用它们来显示我系统的特定作业(基于名称)的活动/归档执行的详细信息。

还可以使用此类实用程序实现自定义的基于计时器的数据收集器,它将将此数据推送到 JMS 或 Websocket。 Spring-batch 也有很好的监听器,你可以实现它,例如自定义 org.springframework.batch.core.ChunkListener 将允许你像更新一样进行“进度条”——你会知道你的块被处理的时刻,从而更新进度出现。

与您最初的 AOP 解决方案相比,使用 Spring 批处理的方法将是直截了当的(纯 java 代码),并且还会解决您的其他问题:持久大更新的事务:它将整个数据集切割成块,并在单个事务中处理每个块。

【讨论】:

    【解决方案3】:

    您的问题不清楚,问题的标题具有误导性。

    你真的可以使用 Spring Aop 来完成你想做的任务,你只需要注入日志调用方法 fetchUserInfo() 和 fecthLegInfoForEachUser() 等。 您还可以使用@Around 进行更好的控制。

    对于性能方面,鉴于这段代码非常有限,您可以轻松地使用 & 不使用 aop 进行一些分析。 请记住,用于日志记录的 AOP 应用非常广泛,而且 Spring 为许多实体和用途(如工厂)创建代理对象,因此经过了良好的测试和性能。

    【讨论】:

    • 如果您不理解问题,请在评论中说,而不是在答案中。
    • 对不起,你是对的,但我在发帖时不允许发表评论。
    【解决方案4】:

    (1)长时间运行的任务意味着“工作”,所以你可能需要:Quartz

    (2)如果你只是想知道你的程序去了哪里,你可能需要一个日志工具,如:Logback。一个定义明确的 appender 将解决你的问题。

    【讨论】:

    • SO 答案不适用于推荐工具或库。
    猜你喜欢
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多