Java 方法中间的横切关注点

Java 方法中间的横切关注点,java,spring,aop,aspectj,spring-aop,Java,Spring,Aop,Aspectj,Spring Aop,AOP(例如AspectJ、SpringAOP)可以方便地处理(建议)以下方法周围切入点处的横切关注点 “三明治”代码 AOP是否容易横切与下面的用户代码重叠的关注点?怎么做 “意大利面”代码 谢谢 虽然某些AOP实现可能允许您这样做,但这可能表明需要将这些方法重构为更复杂的方法,因为如果需要将关注点横切到方法中间,它们可能会做得太多。 这样做会给您带来以下好处: methodX { usercodemethod1(); usercodemethod2(); } userco

AOP(例如AspectJ、SpringAOP)可以方便地处理(建议)以下方法周围切入点处的横切关注点

“三明治”代码

AOP是否容易横切与下面的用户代码重叠的关注点?怎么做

“意大利面”代码


谢谢

虽然某些AOP实现可能允许您这样做,但这可能表明需要将这些方法重构为更复杂的方法,因为如果需要将关注点横切到方法中间,它们可能会做得太多。 这样做会给您带来以下好处:

methodX 
{
    usercodemethod1();
    usercodemethod2();
}

usercodemethod1
{
    user code x1
    crosscut code
}

usercodemethod2
{
    user code x2
    crosscut code
}

SpringAOP没有帮助,因为它只理解execution()切入点

AspectJ包含更多的切入点,包括withincode()构造,这听起来像是您想要的:

withincode(* YourClass.methodX(. .))
这使您可以建议给定方法执行中的所有连接点

阅读更多信息,这是一本关于AspectJ和SpringAOP的非常好的书


编辑:

以下是一些示例代码:

package com.dummy.aspectj;

import java.util.Arrays;
import java.util.Collections;

public class DummyClass{

    public static void main(final String[] args){
        System.out.println(Arrays.asList("One", Collections.singleton("Two")));
        System.out.println("Enough?");
    }

}

package com.dummy.aspectj;

import java.util.Arrays;

public aspect DummyAspect{

    pointcut callWithinMain() : 
        withincode(* com.dummy.aspectj.DummyClass.main(..)) // anything inside DummyClass.main
        && call(* *.*(..));                                 // but only method calls

    before() : callWithinMain() {
        System.out.println("\n***************************************************");
        System.out.println("** Calling:\n**\t"
            + thisJoinPointStaticPart.getSignature()
            + "\n** with arguments:\n**\t "
            + Arrays.deepToString(thisJoinPoint.getArgs()) );
        System.out.println("***************************************************\n");
    }

}
从Eclipse/AJDT运行DummyClass会生成以下输出:

***************************************************
** Calling:
**  Set java.util.Collections.singleton(Object)
** with arguments:
**   [Two]
***************************************************


***************************************************
** Calling:
**  List java.util.Arrays.asList(Object[])
** with arguments:
**   [[One, [Two]]]
***************************************************


***************************************************
** Calling:
**  void java.io.PrintStream.println(Object)
** with arguments:
**   [[One, [Two]]]
***************************************************

[One, [Two]]

***************************************************
** Calling:
**  void java.io.PrintStream.println(String)
** with arguments:
**   [Enough?]
***************************************************

Enough?

我们根据最佳实践进行重构。从总体上讲,重构到AOP是一种好的实践吗?如果不是这样的话,我们承认AOP很容易约束问题域,例如,绿灯到事务划分,红灯到日志记录。我不会说一个人应该仅仅为了适应AOP而重构,但是正如@seanizer所提到的,spring在这方面没有帮助,所以这可能是你最好的选择——任何代理(运行时)基于AOP的AOP通常不支持将代码编织到method@saret:这不适用于基于代理的aop。当methodX调用usercodemethod1(假设它们在同一个类中)时,它不会调用代理,而是调用实际的类(您已经在代理中),因此建议没有机会执行。因此,实现这一点的唯一方法是从外部访问整个工作流(客户端调用usercodemethod1,然后调用usercodemethod2等),这将严重违反DRY原则。@seanizer如果这些方法是可重写的(例如受保护的虚拟方法),则代理可以向它们注入需要cglib的代码,这在基于接口的jdk代理(SpringAOP的标准方法)中是不可能的。您有没有一个方便的示例将其放在这里?谢谢你的启发!
package com.dummy.aspectj;

import java.util.Arrays;
import java.util.Collections;

public class DummyClass{

    public static void main(final String[] args){
        System.out.println(Arrays.asList("One", Collections.singleton("Two")));
        System.out.println("Enough?");
    }

}

package com.dummy.aspectj;

import java.util.Arrays;

public aspect DummyAspect{

    pointcut callWithinMain() : 
        withincode(* com.dummy.aspectj.DummyClass.main(..)) // anything inside DummyClass.main
        && call(* *.*(..));                                 // but only method calls

    before() : callWithinMain() {
        System.out.println("\n***************************************************");
        System.out.println("** Calling:\n**\t"
            + thisJoinPointStaticPart.getSignature()
            + "\n** with arguments:\n**\t "
            + Arrays.deepToString(thisJoinPoint.getArgs()) );
        System.out.println("***************************************************\n");
    }

}
***************************************************
** Calling:
**  Set java.util.Collections.singleton(Object)
** with arguments:
**   [Two]
***************************************************


***************************************************
** Calling:
**  List java.util.Arrays.asList(Object[])
** with arguments:
**   [[One, [Two]]]
***************************************************


***************************************************
** Calling:
**  void java.io.PrintStream.println(Object)
** with arguments:
**   [[One, [Two]]]
***************************************************

[One, [Two]]

***************************************************
** Calling:
**  void java.io.PrintStream.println(String)
** with arguments:
**   [Enough?]
***************************************************

Enough?