Как с помощью рефлексии определить какие методы класса относятся к определённому интерфейсу?
Создаю с помощью рефлексии экземпляр класса MBeanInfo и столкнулся с проблемой поиска методов реализующих определённый интерфейс. К примеру, имеется интерфейс SimpleDynamicMBean и класс Simple его реализующий. Согласно спецификации JMX имя интерфейса должно заканчиваться на DynamicMBean (для динамически управляемого ресурса), т.е. зная имя текущего класса, мы знаем какой интерфейс искать. Но как определить, что конкретный метод класса во-первых переопределён, а во вторых наследуется от определённого интерфейса?
public interface SimpleDynamicMBean
{
// read/write attribute path
public String getPath();
public void setPath( String path );
// read/write attribute severityThreshold
public int getSeverityThreshold();
public void setSeverityThreshold( int threshold);
// read/write attribute active
public boolean isActive();
public void setActive( boolean isActive );
// read-only attribute changesCount
public int getChangesCount();
// write-only attribute
public void setVerboseOutput( boolean isVerbose );
// operation sendMessage
public void sendMessage( String msg );
// operation showSequenceNumber
public int showSequenceNumber();
}
А также класс его реализующий:
public class Simple implements SimpleDynamicMBean
{
private int seq = 1;
private boolean verboseOutput;
private int changesCount;
private String path;
private int severityThreshold;
private boolean active;
public Simple ()
{
for( Method m : this.getClass().getMethods() )
{
// как определить, что метод m is overriden
// и наследуется от SimpleDynamicMBean?
}
}
@Override public String getPath()
{
return this.path;
}
@Override public void setPath( final String path )
{
this.path = path;
this.changesCount++;
}
@Override public int getSeverityThreshold()
{
return this.severityThreshold;
}
@Override public void setSeverityThreshold( final int threshold )
{
this.severityThreshold = threshold;
this.changesCount++;
}
@Override public boolean isActive()
{
return this.active;
}
@Override public void setActive( final boolean isActive )
{
this.active = isActive;
this.changesCount++;
}
@Override public int getChangesCount()
{
return this.changesCount;
}
@Override public void setVerboseOutput( final boolean isVerbose )
{
this.verboseOutput = isVerbose;
this.changesCount++;
}
@Override public void sendMessage( final String message )
{
System.out.println( message );
}
@Override public int showSequenceNumber()
{
return this.seq;
}
}
Ответы (1 шт):
Решил с помощью получения списка всех интерфейсов класса и их последующей фильтрацией, т.к. имя искомого интерфейса задаётся спецификацией и может быть создано исходя из имени класса. Далее уже просто ищем подходящий метод в классе.
На счёт аннотации @Override так и не смог найти решение, так как она не доступна во время выполнения и не может быть определена/прочитана с помощью рефлексии.
Class<?> cls = Simple.class;
String interfaceName = cls.getSimpleName() + "DynamicMBean";
Class<?> interfaceType = Stream.of( cls.getInterfaces() )
.filter( i -> i.getSimpleName().equals( interfaceName ) )
.findAny()
.orElseThrow( () -> new IntrospectionException( "..." ) );
for( Method interfaceMethod : interfaceType.getMethods() )
{
Method clsMethod = clsMethods
.stream()
.filter( m ->
m.getName().equals( interfaceMethod.getName() )
&&
// проверяем сигнатуру метода...
Arrays.equals(
interfaceMethod.getParameterTypes(),
m.getParameterTypes()
)
)
.findAny()
.orElseThrow( () -> new IntrospectionException( "..." ) );
}