Я часть команды, которая разрабатывает довольно большой Java-апплет Swing. Большая часть нашего кода унаследована, и существует множество одноэлементных ссылок. Мы сгруппировали их все в один синглтон «Контекст приложения». Теперь нам нужно создать способ разделения общего контекста (общего для всех отображаемых в данный момент апплетов) и необщего контекста (для каждого отображаемого в данный момент апплета).
Однако у нас нет идентификатора для каждого местоположения, которое вызывает синглтон, и мы не хотим распространять идентификатор на все местоположения. Какой самый простой способ определить, в каком контексте апплета мы работаем? (Я пробовал возиться с загрузчиками классов, группами потоков, идентификаторами потоков ... пока я не мог найти ничего, что позволило бы мне определить источник вызова).




Если я вас правильно понял, идея состоит в том, чтобы получить отдельный объект "singleton" для каждого вызывающего объекта или "контекста". Одна вещь, которую вы можете сделать, - это создать локальную глобальную переменную потока, в которую вы записываете идентификатор текущего контекста. (Это можно сделать с помощью АОП.) Затем в одноэлементном геттере идентификатор контекста извлекается из локального потока для использования в качестве ключа к правильному «одноэлементному» экземпляру для вызывающего контекста.
Что касается АОП, то не должно возникнуть проблем с его использованием в апплетах, поскольку, в зависимости от ваших точек, советы создаются во время компиляции, а JAR добавляется к зависимостям времени выполнения. Следовательно, во время выполнения не должно оставаться никаких особых свидетельств АОП.
@Hugo относительно threadlocal:
Я думал об этом решении. Однако в ходе экспериментов я обнаружил две проблемы с этим подходом:
Синглтоны - это зло, чего вы ждете? ;)
Возможно, наиболее полным подходом будет загрузка основной части апплета в другой загрузчик классов (используйте java.net.URLClassLoader.newInstance). Затем используйте WeakHashMap, чтобы связать загрузчик классов с апплетом. Если бы вы могли разделить большую часть кода на общий загрузчик классов (как родительский для каждого загрузчика классов для каждого апплета) и на обычную кодовую базу апплета, это было бы быстрее, но больше работы.
Другие хаки:
Если у вас есть доступ к какому-либо компоненту, вы можете повторно использовать Component.getParent или SwingUtilities.getRoot.
Если вы находитесь в потоке экземпляра апплета, вы можете настроить ThreadLocal.
Из EDT вы можете прочитать текущее событие из очереди (java.awt.EventQueue.getCurrentEvent ()) и, возможно, найти в нем компонент. В качестве альтернативы отправьте EventQueue с помощью переопределенного метода dispatchEvent.
Это (безусловно) лучшая коллекция идей, которые я видел по этому поводу. Мне особенно нравится «выдвинуть настраиваемую очередь событий» - и я собираюсь ее попробовать.
Вы должны иметь возможность получить новый поток EDT, используя другое значение для тега архива. Я думаю, вы можете просто добавить случайное имя баночки в конец, даже если оно существует.