如何使用AspectJ在AOP中按类,按对象和按方法/源位置部分来创建方面

问题描述

我想为每个类,每个对象以及每个方法/源位置部分创建一个方面实例。

更具体地说:

  • 某些值仅在类之间变化,但每个类仅需要计算一次,因此每个类需要推导一次。例如。存储Class是按类进行的,对于特定的日志记录类,也是对Logger的引用。
  • 有些值因方法而异,但是每个方法只需要计算一次,因此每个方法只需推导一次。例如。方法签名将是每个类的每个方法。由于对象实例或调用,此数据不会更改。
  • 某些值从实例/对象到实例/对象变化,但是每个实例/对象只需要计算一次,因此每个实例/对象需要推论一次。例如。对象ID,具体取决于实例。
  • 某些值随对象的不同而变化,但每个字段或方法的每个对象只需计算一次,因此,每个字段或方法的每个对象只需推导一次。例如。方法调用计数,该计数取决于方法和对象。
  • 某些值随呼叫而变化,因此需要为每个呼叫推导/计算它们。例如。在AspectJ中获取方法参数。这取决于方法,对象和调用

我正在尝试创建存储这些推论/计算值的方面。为了不产生比在内存和计算方面需要更多的东西。如何在Eclipse AspectJ AOP中实现呢?

到目前为止,我一直在尝试创建一个像这样的层次结构:

aspect Base {
    // Singleton - data items for the whole program computed and stored once
    // This is shared across all the objects in the application regardless of the class

    protected pointcut executionJoinPoints(): !within(Base+) && execution (* *.*(..));
}

aspect PerClass extends Base perthis(executionJoinPoints()) {
    // Per class - store class-specific data computed and stored once per class
    // Since this is class-specific,need to kNow what class this corresponds to
    // This is shared across all the objects of the same class
}

aspect PerMethodPerClass extends PerClass percflow(executionJoinPoints()) {
    // Per method - store method specific data computed and stored once per method as fields
    // Since this is method-specific,need to kNow what method this corresponds to
    // This is shared across all the objects of the same class
}

aspect PerObject extends PerMethodPerClass perthis(executionJoinPoints()) {
    // Per object/instance - store object/instance-specific data computed and stored once per object
    // Since this is object/instance-specific,need to kNow what object/instance this corresponds to
    // This is specific to the object/instance
}

aspect PerMethodPerObject extends PerObject percflow(executionJoinPoints()) {
    // Per method per object - store method specific data computed and stored once per method as fields for every object instance
    // Since this is method-specific,need to kNow what method this corresponds to and also what object this corresponds to
    // This is specific to the object/instance and particular method
}


public aspect PerCall extends PerMethodPerInstance {
    // Per call - handle data which change from call to call
    // This is specific to the call or invocation or execution
}

我正在尝试实施:

  • 记录和跟踪
  • 程序执行的度量和统计信息收集

使用AspecJ AOP。对于统计信息,我收集每个类,每个对象以及每个方法/源位置部分需要一个方面实例来存储和收集相关数据。

例如与方法相关的统计信息将在PerMethod方面进行计算和存储。同样,查找特定于方法的计数器比在大型数据结构中查找更容易访问。这里需要的是,对于每种方法,该方面都实例化一次。类,对象等也是如此。

收集执行统计信息会产生一些开销,但是这样做是为了尽量减少开销,因此为什么我要对每种情况都有特定的方面。

我要这是要学习如何在AspectJ中做到这一点,而不是尝试解决特定问题。一旦尝试实施它,可能会弹出一些具体的问题,我可以与他们分享更多我尝试过的具体例子以及所产生的错误或问题。

解决方法

很抱歉将其写为答案,但是评论太长了。

这个问题的问题在于,尽管进行了广泛的解释,您只可以解释如何从技术上做某事,甚至不必说出原因是您正在尝试解决。这使问题成为XY problem的一个很好的例子。

  • 您的方面是什么?
  • 您是否遇到内存或性能问题?
  • 您确定不是将广泛的切入点与建议代码结合使用吗-在先前的问题中,您想详细记录每个方法执行的所有情况,模拟某种调试器,这是问题吗? / li>
  • 您根本有问题吗?如果是这样,则您没有声明。您可能只是在进行过早的优化。

您正试图节省内存和CPU周期,我是从您的问题中得到的。

  • 您是否意识到通过尝试通过per...子句而不是使用默认的AspectJ单例方面实例化模型来创建许多方面实例的事实?
  • 您是否衡量过这是否会使事情变得更好,甚至没有变得更糟?

实际上,您的问题并不代表真正的问题,您所显示的是完全不执行任何操作的层次结构。因此,这样的问题格式与StackOverflow不兼容。这是一个Q / A平台,而不是讨论论坛。我实际上提出了很多要求,而不是为您的问题提出解决方案,这已经是它的症状。固执己见的辩论正是SO的目的所在。因此,就像我之前在其他问题中所说的:提出问题的最佳方法是提供MCVE和清晰的问题描述,其他人可以运行代码并重现您的问题。


更新:如您在AspectJ手册中所见,有以下aspect instantiation types

  • 单人
  • 每个对象(perthis()pertarget()的比较,例如,call()切入点不同,但execution()切入点应该相同)
  • 每个控制流(percflow()percflowbelow()
  • 每种类型(pertypewithin(),描述为here

请注意,“每个控制流”与“每个方法”不同。如所记录的,每当输入特定的控制流时,例如,将创建方面实例。每次执行方法时。如果相同的方法执行了12345次,则将创建12.345个方面实例。因此,如果您希望收集按方法统计信息,则最好将信息存储在相应类的按类型方面实例中。对于您的“按通话”要求,我认为“按控制流”建议是合适的。

现在我们完成了。就像我说的那样,如果您想在这里讨论您的应用程序设计思想,那就错了。因此,我将在这里停止答复,并等待您使用MCVE提出具体的新问题,这些问题可以清晰,正确地回答,而无需引起讨论。我提供了尽可能多的帮助,超出了应有的范围,因为实际上该问题应作为离题的IMO来解决。

祝您有趣的项目顺利。如果您需要更多咨询,我也可以将其作为日常工作,当然可以雇用我。 ;-)

否则,我想鼓励您通过执行一些事情来创建可验证的事实,而不是在这里提出一堆理论问题(到目前为止,我已经回答了其中的3个问题),然后看看您的想法是否可行。您似乎喜欢理论化。思维是好的,但这样做也是。同时使用两者,您将获得更大的进步,并反复验证您的想法。