Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exclude an anonymous inner method from a pointcut?

Tags:

java

aop

aspectj

I have an AspectJ trace routine set up to log method entry and exit conditions using the following pointcuts:

public aspect Trace {       
    pointcut anyMethodExecuted():       execution (* biz.ianw.lanchecker.*.*(..)) && !within(Trace) && !within( is(AnonymousType) );
    pointcut anyConstructorExecuted():  execution (biz.ianw.lanchecker.*.new(..)) && !within(Trace); 

In my sendEmail class I have a method which calls the setDebugOut method to redirect the debug output to a LogOutputStream:

final private static  Logger log = LoggerFactory.getLogger(MailMail.class);
...
LogOutputStream losStdOut = new LogOutputStream() {             
    @Override
    protected void processLine(String line, int level) {
        log.debug(line);
    }
};    

public void sendPlainHtmlMessage(...) {  
    Session session = javaMailSender.getSession();
    PrintStream printStreamLOS = new PrintStream(losStdOut);
    session.setDebugOut(printStreamLOS);
    ...

This works fine, except that the Trace class pointcut intercepts the call the the anonymous inner class, producing as output:

20:14:18.908 TRACE [biz.ianw.lanchecker.Trace] - Enters method: Logger biz.ianw.lanchecker.MailMail.access$0()
20:14:18.909 TRACE [biz.ianw.lanchecker.Trace] - Exits method: Logger biz.ianw.lanchecker.MailMail.access$0().
20:14:18.909 TRACE [biz.ianw.lanchecker.Trace] -   with return value: Logger[biz.ianw.lanchecker.MailMail]
20:14:18.909 DEBUG [biz.ianw.lanchecker.MailMail] - DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]

I added the rather overly broad

&& !within( is(AnonymousType) )

condition to the pointcut, as shown above, but it had no effect. In fact I'm having real difficulty finding is(AnonymousType) documented anywhere.

How can I write a pointcut that excludes this anonymous inner method, preferably without impacting any others?

like image 358
Ian Avatar asked Nov 06 '15 02:11

Ian


1 Answers

This answer is courtesy Andrew Clement (see http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg14906.html, ff), reposted here with his permission:

The access$0 method has been added to MailMail because log is private in MailMail - it enables the log.debug(line) to access log from the anonymous class (presumably called MailMail$1).

Recognizing that, we can see that access$0 is not in the anonymous class, it is an accessor generated in the MailMail class, hence your additional pointcut fragment not working.

Couple of options:

Exclude it specifically:

pointcut anyMethodExecuted():       execution (* biz.ianw.lanchecker.*.*(..)) && !within(Trace) && !execution(* MailMail.access$0(..));

Exclude all synthetic accessors (it is considered synthetic because it is ‘generated’ by the compiler to support what you are doing):

pointcut anyMethodExecuted():       execution (* biz.ianw.lanchecker.*.*(..)) && !within(Trace) && !execution(synthetic * access$*(..));

Or you could exclude all synthetics perhaps:

pointcut anyMethodExecuted():       execution (!synthetic * biz.ianw.lanchecker.*.*(..)) && !within(Trace);
like image 78
Ian Avatar answered Sep 29 '22 17:09

Ian