Есть ли какие-либо библиотеки, которыми инструментальный код, чтобы проверить, что методы обратились к компонентам Swing, называют на Потоке Отправки События? Вероятно, не было бы слишком трудно написать некоторый абсолютный код для того, чтобы сделать это, но я уверен, что существуют пограничные случаи и этажерка, которую обработали другие люди. Я ищу это во времени выполнения хотя, не для модульных тестов.
В инфраструктуре FEST есть инструмент для обнаружения использования Swing вне EDT. По сути, вы устанавливаете RepaintManager. Фреймворк ориентирован на тестирование, но RepaintManager можно использовать во время развертывания.
В качестве альтернативы, чтобы проверить все методы, такие как геттеры и сеттеры, для доступа только к EDT, вы можете использовать AspectJ и ткачество во время загрузки, чтобы добавить SwingUtilities.isDisaptchThread () советует каждому методу в ваших компонентах Swing (и компонентах JDK Swing)
@Aspect
public class EDTCheck {
@Pointcut("call (* javax.swing..*+.*(..)) || " +
"call (javax.swing..*+.new(..))")
public void swingMethods() {}
@Pointcut("call (* com.mystuff.swing..*+.*(..)) || " +
"call (com.mystuff.swing..*+.new(..))")
public void mySwingMethods() {}
@Pointcut("call (* javax.swing..*+.add*Listener(..)) || " +
"call (* javax.swing..*+.remove*Listener(..)) || " +
"call (void javax.swing.JComponent+.setText(java.lang.String))")
public void safeMethods() {}
@Before("(swingMethods() || mySwingMethods()) && !safeMethods()")
public void checkCallingThread(JoinPoint.StaticPart thisJoinPointStatic) {
if(!SwingUtilities.isDispatchThread()) {
System.out.println(
"Swing single thread rule violation: "
+ thisJoinPointStatic);
Thread.dumpStack();
// or you might throw an unchecked exception
}
}
}
(Немного изменено из статьи - добавлен mySwingMethods pointcut и используется SwingUtiliites.isDispatchThread (). На практике это то же самое, что и EventQueue. isDispatchThread (), но абстракция чище.)
Все, что вам нужно, это следующий код:
void method() {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeAndWait(new Runnable() { public void run() { method(); } );
return;
}
// do method code here, guaranteed to be in EDT
}
Кроме того, использование Substance в качестве вашего LAF поможет вам определить, где не выполняются вещи, связанные с Swing. на EDT. У него есть проверки, чтобы убедиться, что все Swing-файлы выполняются в правильном потоке, в противном случае он не работает с исключением.
С точки зрения кодирования, четко отделите код EDT от кода не-EDT. Избегайте SwingWorker
как чумы.
Чтобы подтвердить, что вы находитесь в EDT (вставьте !
для выключенного), добавьте строку:
assert java.awt.EventQueue.isDispatchThread();
Вам понадобится -ea
/ -enableassertions
], чтобы сделать что-нибудь. Однако в основном он работает как исполняемый комментарий.