Давайте предположим, что я хочу применить @Advice.OnMethodEnter
к методам, объявленным в org.springframework.web.context.support.GenericWebApplicationContext
. Для этого я написал этот минимальный агент:
public class SequenceAgent {
public static void premain(final String args,
final Instrumentation instrumentation) {
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.type(nameStartsWith(
"org.springframework.web.context.support.GenericWebApplicationContext"))
.transform((builder, typeDescription, classLoader, module) -> builder
.method(any()).intercept(Advice.to(SequenceAdvice.class)))
.installOn(instrumentation);
}
public static class SequenceAdvice {
@Advice.OnMethodEnter
static void enter(@Advice.This Object thiz, @Advice.Origin Method method,
@Advice.AllArguments Object... args) {
String className = thiz.getClass().getName();
String methodName = method.getName();
System.out.println("Entered: " + className + "#" + methodName);
}
}
}
Я ожидал, что эта конфигурация отфильтрует org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
, так как она не соответствует org.springframework.web.context.support.GenericWebApplicationContext
, но похоже, что вызов методов для объектов этого класса также перехватывается:
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
public class AgentTest {
public static void main(String[] args) {
AnnotationConfigServletWebServerApplicationContext context =
new AnnotationConfigServletWebServerApplicationContext();
context.containsBean("SomeBean");
}
}
При подключении к агенту и его запуске он распечатывается (упакован для удобства чтения):
Entered: org.springframework.boot.web.servlet.context.
AnnotationConfigServletWebServerApplicationContext
#getResourcePatternResolver
.
.
.
Entered: org.springframework.boot.web.servlet.context.
AnnotationConfigServletWebServerApplicationContext
#getResourceCache
Entered: org.springframework.boot.web.servlet.context.
AnnotationConfigServletWebServerApplicationContext
#getClassLoader
Entered: org.springframework.boot.web.servlet.context.
AnnotationConfigServletWebServerApplicationContext
#containsBean
И иерархия классов для org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServe.ApplicationContext
:
org.springframework.core.io.DefaultResourceLoader
⇧
org.springframework.context.support.AbstractApplicationContext
⇧
org.springframework.context.support.GenericApplicationContext
⇧
⤏⤏⤏⤏ org.springframework.web.context.support.GenericWebApplicationContext
⇧
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
⇧
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServe.ApplicationContext
И метод containsBean
объявлен и переопределен в:
org.springframework.beans.factory.BeanFactory#containsBean
⇧
org.springframework.context.support.AbstractApplicationContext#containsBean
Почему для containsBean
, @Advice.This Object thiz
разрешено до org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
, а не org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
?