简体   繁体   中英

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.

I am fully aware of all JSR-330 compliant IoC containers, like Spring, Guice or 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".

There is one part of the JSR-330 specification which I find slightly troublesome to implement:

A method annotated with @Inject that overrides another method annotated with @Inject will only be injected once per injection request per instance. A method with no @Inject annotation that overrides a method annotated with @Inject will not be injected.

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
  • 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.

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...

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 )

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 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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