在我对您其他问题的回答的基础上,我将向您解释您可以做什么。一些提示:
而不是before()
andafter()
你可以只使用around()
.
您不应该在单例方面为流程实例使用私有成员,因为如果您在多个线程中有异步流程,则可能会覆盖该成员。因此,您的方法不是线程安全的,您应该改用局部变量。
after()
您不应该在通知中打印“进程成功运行”,因为after()
它也会在异常之后运行。因此,您不能安全地假设该过程成功运行,只能假设它完全运行。你应该写“完成的过程”或类似的。顺便说一句,如果您想区分成功的流程和以异常结束的此类流程,您可能需要查看切入点类型after() returning
和after() throwing()
.
使用抽象基类而不result
直接在那里定义成员是没有意义的。如果您可以将其作为父类中的受保护成员,为什么要将其添加为每个子类中的私有成员?我们仍然在这里做 OOP(当然除了 AOP),对吧?优点是您可以使用基类直接从切面访问成员,就像您已经在切入点中所做的那样。
这是适合您的MCVE:
进程类:
package de.scrum_master.app;
import java.io.IOException;
import java.util.Map;
public abstract class RunnableProcess {
protected String result = "foo";
public abstract void run(Map processContext) throws IOException;
}
package de.scrum_master.app;
import java.io.IOException;
import java.util.Map;
public class FirstRunnableProcess extends RunnableProcess {
@Override
public void run(Map processContext) throws IOException {
System.out.println("I am #1");
result = "first";
}
}
package de.scrum_master.app;
import java.io.IOException;
import java.util.Map;
public class SecondRunnableProcess extends RunnableProcess {
@Override
public void run(Map processContext) throws IOException {
System.out.println("I am #2");
result = "second";
}
}
驱动应用:
package de.scrum_master.app;
import java.io.IOException;
public class Application {
public static void main(String[] args) throws IOException {
new FirstRunnableProcess().run(null);
new SecondRunnableProcess().run(null);
}
}
方面:
在这里,您只需将target()
对象绑定到切入点中的参数并在两个建议中使用它。
package de.scrum_master.aspect;
import static org.slf4j.LoggerFactory.getLogger;
import org.slf4j.Logger;
import de.scrum_master.app.RunnableProcess;
import java.util.Map;
public privileged aspect ProcessRunInterceptorProtocol {
pointcut runProcess(RunnableProcess process) :
call(void RunnableProcess.run(Map)) && target(process);
before(RunnableProcess process): runProcess(process) {
Logger logger = getLogger(process.getClass());
logger.info("logger = " + logger);
logger.info("running process = " + thisJoinPoint);
}
after(RunnableProcess process): runProcess(process) {
Logger logger = getLogger(process.getClass());
logger.info("finished process = " + thisJoinPoint);
logger.info("result = " + process.result);
}
}
带有 JDK 日志记录的控制台日志(删除了一些噪音):
INFORMATION: logger = org.slf4j.impl.JDK14LoggerAdapter(de.scrum_master.app.FirstRunnableProcess)
INFORMATION: running process = call(void de.scrum_master.app.FirstRunnableProcess.run(Map))
I am #1
INFORMATION: finished process = call(void de.scrum_master.app.FirstRunnableProcess.run(Map))
INFORMATION: result = first
INFORMATION: logger = org.slf4j.impl.JDK14LoggerAdapter(de.scrum_master.app.SecondRunnableProcess)
INFORMATION: running process = call(void de.scrum_master.app.SecondRunnableProcess.run(Map))
I am #2
INFORMATION: finished process = call(void de.scrum_master.app.SecondRunnableProcess.run(Map))
INFORMATION: result = second