这里是我对AOP理论的理解,只是为了澄清,所以如果你看到一些看起来不对的东西
public class LoggingAspect
{
// ...
public void log(String msg) { ... }
}
public class ExceptionHandlingAspect
{
// ..
public void handle(Exception exc) { ... }
}
public class NonAOPCode
{
// ...
@LoggingAspect @ExceptionHandlingAspect
public void foo()
{
// do some stuff...
}
}
// Now in the driver
public static int main void(String[] args)
{
NonAOPCode nonAOP = new NonAOPCode();
nonAOP.foo();
}
// The AspectWeaver *magically* might weave in method calls so main now becomes:
{
NonAOPCode nonAOP = new NonAOPCode();
log(someMsg);
nonAOP.foo();
handle(someExc);
}
是否对目标或基于Java的AOP有所了解,以及为什么?如何正确使用注释来实现方面,建议,连接点,切入点和这个所谓的方面编织器?
发布于 2018-03-28 13:49:37
假设您想使用@LogExecTime
注释记录某些注释方法所花费的时间。
我首先创建一个注释LogExecTime
:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecTime {
}
然后我定义一个方面:
@Component // For Spring AOP
@Aspect
public class LogTimeAspect {
@Around(value = "@annotation(annotation)")
public Object LogExecutionTime(final ProceedingJoinPoint joinPoint, final LogExecTime annotation) throws Throwable {
final long startMillis = System.currentTimeMillis();
try {
System.out.println("Starting timed operation");
final Object retVal = joinPoint.proceed();
return retVal;
} finally {
final long duration = System.currentTimeMillis() - startMillis;
System.out.println("Call to " + joinPoint.getSignature() + " took " + duration + " ms");
}
}
}
我创建了一个类,用于LogExecTime
:
@Component
public class Operator {
@LogExecTime
public void operate() throws InterruptedException {
System.out.println("Performing operation");
Thread.sleep(1000);
}
}
而一个主要使用Spring AOP的人:
public class SpringMain {
public static void main(String[] args) throws InterruptedException {
ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
final Operator bean = context.getBean(Operator.class);
bean.operate();
}
}
如果我运行这个类,我在stdout上得到以下输出:
Starting timed operation
Performing operation
Call to void testaop.Operator.Operate() took 1044 ms
现在带着魔力。就像我使用Spring AOP而不是AspectJ Weaver一样,这种魔法在运行时使用代理机制发生。所以.class
文件保持不变。例如,如果我调试这个程序并在operate
你放置一个断点,你会看到Spring如何表现神奇:
由于Spring AOP实现是非侵入式的并且使用Spring机制,因此需要添加@Component
注释并使用Spring上下文而不是普通的方式创建对象new
。
另一方面的AspectJ会更改.class
文件。我用AspectJ尝试了这个项目,并用jad反编译运算符类。这导致:
public void operate()
throws InterruptedException
{
JoinPoint joinpoint = Factory.makeJP(ajc$tjp_0, this, this);
operate_aroundBody1$advice(this, joinpoint, LogTimeAspect.aspectOf(), (ProceedingJoinPoint)joinpoint, (LogExecTime)(ajc$anno$0 == null && (ajc$anno$0 = testaop/Operator.getDeclaredMethod("operate", new Class[0]).getAnnotation(testaop/LogExecTime)) == null ? ajc$anno$0 : ajc$anno$0));
}
private static final void operate_aroundBody0(Operator ajc$this, JoinPoint joinpoint)
{
System.out.println("Performing operation");
Thread.sleep(1000L);
}
private static final Object operate_aroundBody1$advice(Operator ajc$this, JoinPoint thisJoinPoint, LogTimeAspect ajc$aspectInstance, ProceedingJoinPoint joinPoint, LogExecTime annotation)
{
long startMillis = System.currentTimeMillis();
Object obj;
System.out.println("Starting timed operation");
ProceedingJoinPoint proceedingjoinpoint = joinPoint;
operate_aroundBody0(ajc$this, proceedingjoinpoint);
Object retVal = null;
obj = retVal;
long duration = System.currentTimeMillis() - startMillis;
System.out.println((new StringBuilder("Call to ")).append(joinPoint.getSignature()).append(" took ").append(duration).append(" ms").toString());
return obj;
Exception exception;
exception;
long duration = System.currentTimeMillis() - startMillis;
System.out.println((new StringBuilder("Call to ")).append(joinPoint.getSignature()).append(" took ").append(duration).append(" ms").toString());
throw exception;
}
private static void ajc$preClinit()
{
Factory factory = new Factory("Operator.java", testaop/Operator);
ajc$tjp_0 = factory.makeSJP("method-execution", factory.makeMethodSig("1", "operate", "testaop.Operator", "", "", "java.lang.InterruptedException", "void"), 5);
}
private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0; /* synthetic field */
private static Annotation ajc$anno$0; /* synthetic field */
static
{
ajc$preClinit();
}
https://stackoverflow.com/questions/-100007828
复制相似问题