查找和运行私有注释方法的最简单方法是什么?

时间:2016-10-13 13:09:24

标签: java reflection annotations private-members

以下示例仅在公共时运行MyClass#myMethod()。如果它是私有的,它不会运行它。

即使私有也如何运行?

import org.apache.commons.lang3.reflect.MethodUtils;

import javax.annotation.PostConstruct;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Created by dims on 13.10.2016.
 */
public class CallPrivateMethodTest {

   @Retention(RUNTIME)
   @Target(METHOD)
   public @interface MyAnnotation {
   }

   public static class MyClass {

      @MyAnnotation
      private void myMethod() {
         System.out.println("myMethod() ran");
      }
   }

   public static void main(String[] args) {

      MyClass myObject = new MyClass();

      List<Method> methods = MethodUtils.getMethodsListWithAnnotation(myObject.getClass(), MyAnnotation.class);


      for(int i=0; i<methods.size(); ++i) {
         try {
            methods.get(i).invoke(myObject);
         } catch (IllegalAccessException e) {
            e.printStackTrace();
         } catch (InvocationTargetException e) {
            e.printStackTrace();
         }
      }
   }
}

3 个答案:

答案 0 :(得分:1)

您必须在方法上致电setAccessible(true)

请参阅the Javadoc of AccessibleObject,而It seems that MethodUtils#getMethodsListWithAnnotation又是Method的超类型。

在你的例子中:

methods.get(i).setAccessible(true);
methods.get(i).invoke(myObject);

编辑:正如GhostCat在他的回答中指出的那样,并非所有的反射调用都会返回私有方法。 SkipList实际上并没有归还它们。

要解决此问题,您必须自己获取这些方法:

MyClass myObject = new MyClass ();

Method[] allMethods = myObject.getClass ().getDeclaredMethods ();
List<Method> annotatedMethods = Arrays.stream (allMethods)
                                      .filter (m -> m.getAnnotation (MyAnnotation.class) != null)
                                      .collect (Collectors.toList ());

for (Method method: annotatedMethods) {
  try {
    method.setAccessible (true);
    method.invoke (myObject);
  } catch (IllegalAccessException e) {
    e.printStackTrace ();
  } catch (InvocationTargetException e) {
    e.printStackTrace ();
  }
}

答案 1 :(得分:0)

基本上,您需要从类本身运行私有方法。也许你应该重新考虑你的代码?否则,亚历克斯的回答将起到作用。

有关访问级别的更多信息:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

如果你想使用Reflection,你可以在这里找到关于这种行为的更多信息:Java reflection - impact of setAccessible(true)

答案 2 :(得分:0)

实际上,您的代码不起作用有两个原因:

  1. 该私人方法出现在该列表中;但在打电话之前,你必须让它可访问(你已经得到了答案)
  2. 根据您正在使用的Util类的实现,也许getMethodsListWithAnnotation会返回一个不包含任何私有方法的列表? (你看,java反射中用于保持私有方法的机制与 public 方法不同。因此,如果该util类正在生成相同的内容,我将不会感到惊讶另外)。
  3. 在任何情况下:私有方法都是私有的原因。它们代表内部实施详细信息。它们可能会一直更改

    从这个意义上说:你真正的问题是你认为有一个合理的理由来使用反射来调用私有方法。您应该使用第一个。如果你真的认为该方法应该注释;并通过反思来调用;然后至少让它公开