简体   繁体   English

Java:如何使用反射检查方法是否被覆盖

[英]Java: How to check if a method is overridden, using reflection

I need to do some processing to determine the dependencies of JSR-330 annotated classes, using reflection. 我需要做一些处理来确定JSR-330带注释类的依赖关系,使用反射。

I am fully aware of all JSR-330 compliant IoC containers, like Spring, Guice or PicoContainer. 我完全了解所有符合JSR-330标准的IoC容器,如Spring,Guice或PicoContainer。 However, what I need is not to resolve and inject dependencies, but to identify them. 但是,我需要的不是解决和注入依赖关系,而是要识别它们。

That basically means I need to implement the JSR-330 implementation, at least when it comes to reflective class "parsing". 这基本上意味着我需要实现JSR-330实现,至少在涉及反射类“解析”时。

There is one part of the JSR-330 specification which I find slightly troublesome to implement: JSR-330规范的一部分我觉得实现起来有点麻烦:

A method annotated with @Inject that overrides another method annotated with @Inject will only be injected once per injection request per instance. 使用@Inject注释的方法将覆盖另一个使用@Inject注释的方法,每个实例的每个注入请求只会注入一次。 A method with no @Inject annotation that overrides a method annotated with @Inject will not be injected. 不会注入没有@Inject批注的方法,该方法将覆盖使用@Inject注释的方法。

That means that subclasses can redefine the autowiring contract of their base class, as well as hook into the injection flow (through polymorphism). 这意味着子类可以重新定义其基类的自动装配合同,以及挂钩注入流(通过多态)。

Here comes my question: Given a class hierarchy, is there an easy way to check whether a method at some part of the hierarchy is overridden further down the hierarchy? 我的问题出现了: 给定一个类层次结构,是否有一种简单的方法可以检查层次结构某些部分的方法是否在层次结构的下方被覆盖?

The simplest way I would do this in my case is with recursion from the leaf of the hierarchy: 在我的例子中,我最简单的方法是从层次结构的叶子中递归:

private List<Method> getInjectableMethods(final Class<?> clazz) {
    // recursive stop condition
    if(clazz == null) {
        return emptyList();
    }

    // recursively get injectable methods from superclass
    final List<Method> allInjectableMethods = newLinkedList(getInjectableMethods(clazz.getSuperclass()));
    final List<Method> injectableMethods = newArrayList();

    // any overridden method will be present in the final list only if it is injectable in clazz
    for (final Method method : clazz.getDeclaredMethods()) {
        removeIf(allInjectableMethods, Methods.Predicates.overriddenBy(method));
        if (isInjectable(method)) {
            injectableMethods.add(method);
        }
    }
    allInjectableMethods.addAll(injectableMethods);

    return allInjectableMethods;
}

As for the overriddenBy Guava-like Predicate, I would check that: 至于被覆盖的类似番石榴的谓词,我会检查:

  • The methods defining classes are in an isAssignableFrom relation 定义类的方法是isAssignableFrom关系
  • The methods name is the same 方法名称是相同的
  • The methods formal parameters are the same 方法形式参数是相同的

The resulting complexity is O(n^2) with regard to the number of methods in the hierarchy. 对于层次结构中的方法数量,产生的复杂度为O(n ^ 2)。

I was wondering if there was some easier or more efficient way to achieve it, or any libraries with such functionality. 我想知道是否有更简单或更有效的方法来实现它,或任何具有此类功能的库。 I've looked unsuccessfully in both Guava and Apache Commons... 我在Guava和Apache Commons中看起来都没有成功......

Unfortunately, class graph is navigable only in root direction - so there is no way to find all derived classes except to check all classes available to certain classloader. 不幸的是,类图只能在根方向导航 - 所以除了检查某些类加载器可用的所有类之外,无法找到所有派生类。 IoC containers do not have this problem, because they always know concrete implementation ( it is part of configuration ) IoC容器没有这个问题,因为它们总是知道具体的实现(它是配置的一部分)

Inheritance trees are usually built by IDEs, but AFAIUK they use brite force indexing over all available sources / classes ( you may look into sources of community editio of InteliiJ IDEA for clues ) 继承树通常由IDE构建,但是AFAIUK它们对所有可用的源/类使用brite force索引(您可以查看InteliiJ IDEA的社区editio的来源以获取线索)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM