I am working on a project that is basically a lot of processes that run periodically. Each process is a different class that extends an abstract class RunnableProcess
we created, which contains a private
attribute Map<String, String> result
and the abstract method run
with the signature below:
public abstract void run(Map processContext) throws IOException;
To improve modularization on the project, I'm starting to use Aspect Oriented Programming (AOP) to intercept the run
calls from every RunnableProcess
. I am still learning AOP, and I have the following code until now:
import static org.slf4j.LoggerFactory.getLogger;
import org.slf4j.Logger;
import process.RunnableProcess;
import java.util.Map;
public aspect ProcessRunInterceptor {
private Logger logger;
pointcut runProcess() : call(void RunnableProcess.run(Map));
after(): runProcess() {
logger = getLogger(thisJoinPoint.getClass());
logger.info("process run successfully");
}
}
It is working, but I want to log more information than just "process run successfully"
. I have this information inside the intercepted class, in the result
attribute mentioned above. Is it possible to access it in the advice without changing the implementation of RunnableProcess
?
I can (prefer not to, but if it would be the only choice...) change the attribute from private
to protected
, but I wouldn't change it to public
. I also would not like to create a get
method for it.
Building upon my answer to your other question, I will explain to you what you can do. A few hints:
Instead of
before()
andafter()
you could just usearound()
.You should not use a private member for the process instance in a singleton aspect because if you have asynchronous processes in multiple threads, the member could be overwritten. Thus, your approach is not thread-safe and you should use a local variable instead.
You should not print "process run successfully" in an
after()
advice becauseafter()
also runs after an exception. So you cannot safely assume that the process ran successfully, only that it ran at all. You should rather write "finished process" or similar. BTW, if you want to differentiate between successful processes and such ending with an exception, you might want to look into pointcut typesafter() returning
andafter() throwing()
.It does not make sense to use an abstract base class and not define the member
result
there directly. Why add it as a private member in each subclass if you can have it as a protected member in the parent? We are still doing OOP here (beside AOP, of course), right? The advantage is that you can access the member directly from the aspect using the base class like you already do in your pointcut.Here is an MCVE for you:
Process classes:
Driver application:
Aspect:
Here you just bind the
target()
object to a parameter in the pointcut and use it in both advices.Console log with JDK logging (some noise removed):