您如何确定 CLASS 是否是 spring 代理?

How do you figure out whether a CLASS is a spring proxy?

一言以蔽之

AopUtils中,我们有

    /**
     * Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
     * <p>This method additionally checks if the given object is an instance
     * of {@link SpringProxy}.
     * @param object the object to check
     * @see #isJdkDynamicProxy
     * @see #isCglibProxy
     */
    public static boolean isAopProxy(@Nullable Object object) {
        return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) ||
                object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)));
    }

现在想检查一个 bean class 是否在 BeanFactoryPostProcessor.

中被代理而不实例化 bean(即只用它的 class)

我以为我可以“翻译”上面的方法:

    private fun <T> isAopProxyClass(candidate: Class<T>): Boolean {
        return SpringProxy::class.java.isAssignableFrom(candidate)
            && (
            Proxy.isProxyClass(candidate)
                || candidate.name.contains(CGLIB_CLASS_SEPARATOR)
            )
    }

但这不会检测代理,因为 SpringProxy::class.java.isAssignableFrom(candidate)false,即使对于明显被代理的 classes。

如何进行这项工作?

全图

我在 BeanFactoryPostProcessor 中,我需要未代理的 bean classes 来通过反射访问某些带注释的方法。

访问发生在 lambda 函数中,该函数将首先使用 ApplicationContext 检索 class 的 bean。不能在此 BeanFactoryPostProcessor 中强制实例化 bean(事实上,如果这样做,应该抛出异常,因为某些 bean 是会话范围的)。

有趣的问题。

屏幕截图中突出显示的三个 class 是 CGLIB 代理,但不是 AOP 代理。看他们的class名字:都是Spring配置class。但这并不能使它们成为正常的 Spring 代理,尤其是 AOP 代理。关于 @Component@Configuration 之间的区别,以及关于代理和 self-invocation 行为,请阅读

因此,Spring @Configuration class 也不像普通 Spring 代理那样实现 SpringProxy

所以基本上你的解决方案工作得很好,不用担心,据我所知。

P.S.: 我是 Java 人,不是 Kotlin 人。所以我 re-implemented 你的代码来自 Java 的截图,所以我可以调试它并重现你的情况。但即使在 Kotlin 中,我也必须 re-type 一切。下次请将代码发布为可复制的文本,而不仅仅是图像。


更新:如果你检查类似

的内容
beanClasses.stream()
  .filter(aClass -> 
    aClass.getName().contains(CGLIB_CLASS_SEPARATOR) && 
      aClass.getSuperclass().getAnnotation(Configuration.class) == null
  )
  .collect(Collectors.toList())

您应该看到一个空集合,而

beanClasses.stream()
  .filter(aClass -> 
    aClass.getName().contains(CGLIB_CLASS_SEPARATOR) && 
      aClass.getSuperclass().getAnnotation(Configuration.class) != null
  )
  .collect(Collectors.toList())

应该产生与

相同的 classes 列表
beanClasses.stream()
  .filter(aClass -> aClass.getName().contains(CGLIB_CLASS_SEPARATOR))
  .collect(Collectors.toList())

beanClasses 中所有剩余的 CGLIB 代理实际上应该是配置,而不是正常的 Spring 代理。