Harel Farkash
Harel Farkash

Reputation: 167

Trigger a method when calling another method in java (or how to do aop without aop)

I'm trying to achieve the functionality of "before" and "after" method invocation.

  1. I tried spring-aop, but it was buggy (I suspect that it's the combination of groovy in my java application).

  2. I don't want to use java reflection.

  3. I think that creating a method with function as parameter is not suitable here because the functions already exists in another class.

Here's what I'm trying to do (this is only part of the activities, I have 10 more like this):

            long startTimeMetric = System.nanoTime()
            Timer timer = meterRegistry.timer("item 1")
            myObject.theActivity(mediaContainer)
            timer.record(System.nanoTime() - startTimeMetric, TimeUnit.NANOSECONDS)

            long startTimeMetric = System.nanoTime()
            Timer timer = meterRegistry.timer("item 2")
            myObject2.theActivity2(mediaContainer)
            timer.record(System.nanoTime() - startTimeMetric, TimeUnit.NANOSECONDS)

How can I make the repetitive first second and fourth line in each bucket automatic and elegant?

Thanks ahead.

edit: The problem I mentioned with aop is that I'm getting all of the sudden null pointers, whereas without the aop, it was OK. How did I implement the aop?


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMonitor{}

@Aspect
@Component
public class TimeMonitoringAspect {

    @Autowired
    MeterRegistry meterRegistry;

    @Around("@annotation(com.path.to.MyMonitor)")
    public void before(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTimeMetric = System.nanoTime();
        String methodName = joinPoint.getSignature().getName();
        Timer timer = meterRegistry.timer(methodName);
        joinPoint.proceed();
        timer.record(System.nanoTime() - startTimeMetric, TimeUnit.NANOSECONDS);
    }

}

For each method that I wanted to measure time, I annotated @MyMonitor before the method, and it worked most of the time, but in some cases, it gave the null pointer as I mentioned.

Upvotes: 1

Views: 946

Answers (2)

João Pedro Schmitt
João Pedro Schmitt

Reputation: 1488

I would suggest to use lambda expressions:

    public static void main(String[] args) {
        executeActivity(meterRegistry, "item 1", Task::theActivity, mediaContainer);
        executeActivity(meterRegistry, "item 2", Task::theActivity2, mediaContainer);
    }

    public static void executeActivity(MeterRegistry meterRegistry, String name, Consumer<Object> theActivity, Object mediaContainer) {
        long startTimeMetric = System.nanoTime();
        Timer timer = meterRegistry.timer(name);
        theActivity.accept(mediaContainer);
        timer.record(System.nanoTime() - startTimeMetric, TimeUnit.NANOSECONDS);

    }
    public interface MeterRegistry {

        Timer timer(String name);

        void record(Long time);
    }

Upvotes: 0

Sambit
Sambit

Reputation: 8011

As far as AOP is concerned, you can still achieve using the following approaches.

  1. Using Decorator Pattern. Refer this link and this link
  2. You can use Java's InvocationHandler, refer this link. However it uses Proxy.
  3. You can also use CGLib, refer this link. It uses reflection.

Spring provides a easy way to AOP which is used in most cases.

Upvotes: 2

Related Questions