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



以下示例仅在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();
         }
      }
   }
}

你必须在你的方法中调用setAccessible(true)

参见AccessibleObject的Javadoc,它又是Method的超类型。

在你的例子中:

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

EDIT:正如GhostCat在他的回答中指出的,并不是所有的反射调用都返回私有方法。似乎MethodUtils#getMethodsListWithAnnotation实际上并没有返回它们。

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

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 ();
  }
}

基本上,需要从类本身运行一个私有方法。也许你应该重新考虑你的代码?否则,Alex的答案就会起作用。

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

如果你想使用反射,你可以在这里找到更多关于行为的信息:Java反射- setAccessible(true)的影响

实际上,您的代码不能工作可能有两个原因:

  1. 那个私有方法出现在那个列表中;但是在调用它之前,你必须使它可访问(你已经得到了答案)
  2. 取决于你正在使用的Util类的实现,也许getMethodsListWithAnnotation返回一个列表,根本不包括任何私有方法?(您可以看到,Java反射中获取私有方法的机制与获取公共方法的机制不同。因此,如果util类做出同样的区分,我不会感到惊讶)。
在任何情况下:private方法是private是有原因的。它们表示内部实现细节。它们可能随时更改。在这个意义上:你真正的问题是你认为有一个使用反射调用私有方法的正当理由。您应该先处理。如果你真的认为那个方法应该被注释;并通过反射被召唤;那么至少让public

相关内容

  • 没有找到相关文章