gpt4 book ai didi

java - Spring AOP 和 AspectJ 加载时编织 : Around advice will be invoked twice for private methods

转载 作者:行者123 更新时间:2023-12-02 04:06:42 27 4
gpt4 key购买 nike

我将使用 Spring AOP 和 AspectJ Load-Time Weaving 来测量代码中特定私有(private)/ protected /公共(public)方法的执行时间。

为此,我编写了以下注释,我将注释应测量执行时间的方法:

package at.scan.spring.aop.measuring;

import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotation for pointcut associated with the advice {@link MeasuringAspect#aroundAdvice(ProceedingJoinPoint)}.
* @author ilyesve
* @since 02.12.2015
*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Measured {

}

我还写了以下方面:

package at.scan.spring.aop.measuring;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* An aspect which contains an advice to measure execution of methods that are annotated with {@link Measured} if it
* is enabled.
* After the execution of the annotated method the captured data over its execution will be forwarded to the
* configured {@link MeasuringReporter}.
* @author ilyesve
* @since 02.12.2015
*/
@Aspect
public class MeasuringAspect {

/** LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(MeasuringAspect.class.getPackage().getName());

/** Determines whether the Around advice is enabled. Default is disabled. */
private boolean enabled = false;

/** The {@link MeasuringReporter} to report the captured measuring data. */
private MeasuringReporter reporter;

/**
* The Around advice which will be executed on calling of methods annotated with {@link Measured}.
* @param pjp the join point
* @throws Throwable on failure
* @return result of proceeding of the join point
*/
@Around("@annotation(Measured)")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
Object result = null;

if (enabled && reporter != null) {
LOGGER.debug("Starting measuring of method '{}.{}()'...",
pjp.getSignature().getDeclaringTypeName(),
pjp.getSignature().getName());

MeasuringDataDto measuringData = new MeasuringDataDto(pjp.getSignature(), pjp.getArgs());

measuringData.setStartTs(System.currentTimeMillis());
try {
measuringData.setResult(pjp.proceed());
} catch (Throwable t) {
measuringData.setThrowable(t);
}
measuringData.setEndTs(System.currentTimeMillis());

try {
reporter.report(measuringData);
} catch (Throwable t) {
LOGGER.error("Unable to report captured measuring data because of an error. MeasuringData [{}]",
ReflectionToStringBuilder.toString(measuringData, ToStringStyle.DEFAULT_STYLE, true, true),
t);
}

if (measuringData.getThrowable() != null) {
throw measuringData.getThrowable();
}

result = measuringData.getResult();
} else {
result = pjp.proceed();
}

return result;
}

/**
* @param theEnabled if {@code true} the contained advice will be enabled, otherwise disabled
*/
public final void setEnabled(final boolean theEnabled) {
enabled = theEnabled;
if (enabled && reporter != null) {
LOGGER.info("Methods will be measured. Reporter [{}]", reporter.getClass().getCanonicalName());
}
}

/**
* @param theReporter the {@link MeasuringReporter} to be used to report the captured measuring data about
* execution of an method annotated with {@link Measured}
*/
public final void setReporter(final MeasuringReporter theReporter) {
reporter = theReporter;
if (enabled && reporter != null) {
LOGGER.info("Methods will be measured. Reporter [{}]", reporter.getClass().getCanonicalName());
}
}
}

我的Spring配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
default-autowire="byName">

<context:load-time-weaver aspectj-weaving="autodetect" />

<bean id="measuringAspect" class="at.scan.spring.aop.measuring.MeasuringAspect"
factory-method="aspectOf">
<property name="enabled" value="${measuring.enabled}" />
<property name="reporter" ref="measuringReporterService" />
</bean>
</beans>

我还在项目的目录 src/main/resources/META-INF 中放置了以下 aop.xml:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<include within="at.scan..*" />
</weaver>
<aspects>
<aspect name="at.scan.spring.aop.measuring.MeasuringAspect" />
</aspects>
</aspectj>

我还向我的 POM 添加了以下 Spring AOP 和/或 AspectJ 特定依赖项:

  • org.aspectj:aspectjrt:1.8.6
  • org.aspectj:aspectjtools:1.8.6
  • org.springframework:spring-aop:4.1.6

此外,我通过启动 Tomcat 使用 org.aspectj:aspectweaver:1.8.6 作为 Java 代理。

对于带注释的公共(public)方法和 protected 方法来说一切正常,但对于带注释的私有(private)方法,我方面的周围建议将被调用两次,我不知道为什么。

最佳答案

您的切入点表达式与连接点主题具有 @Measured 注释的所有连接点相匹配。这包括两者方法执行方法调用类型连接点。您可能会看到建议在私有(private)方法上执行两次,只是因为您的私有(private)方法是从建议的类本地调用的方法。如果您有从建议代码到其他可见性的@Measured注释方法的方法调用,您会看到这些方法上的双重建议执行如下嗯,不仅仅是私有(private)方法。解决方案是更改切入点表达式,将连接点限制为方法执行或方法调用。我对你的情况的猜测是方法执行本身,所以你的切入点表达式将变成这样:

@Around("execution(@Measured * *(..))")

由于您没有在建议中的任何位置绑定(bind)注释,因此您甚至不需要 @annotation(Measured) 部分。

在项目中设置新方面时,最好通过在 aop.xml 中启用 -showWeaveInfo-verbose 来检查编织过程。

<weaver options="-showWeaveInfo -verbose">
...
</weaver>

这将公开与这些类似的标准错误日志消息(也请注意行号):

[AppClassLoader@62b103dd] weaveinfo Join point 'method-call(void at.scan.spring.aop.measuring.MeasuredClass.test3())' in Type 'at.scan.spring.aop.measuring.MeasuredClass' (MeasuredClass.java:18) advised by around advice from 'at.scan.spring.aop.measuring.MeasuringAspect' (MeasuringAspect.java)
[AppClassLoader@62b103dd] weaveinfo Join point 'method-execution(void at.scan.spring.aop.measuring.MeasuredClass.test3())' in Type 'at.scan.spring.aop.measuring.MeasuredClass' (MeasuredClass.java:27) advised by around advice from 'at.scan.spring.aop.measuring.MeasuringAspect' (MeasuringAspect.java)

关于java - Spring AOP 和 AspectJ 加载时编织 : Around advice will be invoked twice for private methods,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34218012/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com