getSystemResource () против getResource () с соответствующим ClassLoader

Вопрос первый:

ClassLoader.getSystemResource("img.png"); в точности такой же, как ClassLoader.getSystemClassLoader().getResource("img.png");, и в чем разница (какой из них предпочесть?). Я ожидаю ответа «ни то, ни другое» (внутри серверов приложений), так зачем нам эти методы в API?

Вопрос второй:

Имея мое WAR / приложение в Tomcat / другом AppServer, я должен всегда использовать Thread.currentThread().getContextClassLoader().getResourceAsStream("img.png"), не думая о каких-либо вариантах использования, где что-то еще более подходящее (скажем, objOfMyOwnClassCreatedAnywhereWithinMyApp.getClass().getClassLoader().getResource("sth")?

Подытоживая то, что я знаю:

ClassLoader.getSystemResource("img.png");

vs

ClassLoader.getSystemClassLoader().getResource("img.png");

vs

Thread.currentThread().getContextClassLoader().getResource("sth");
My.class.getClassLoader().getResource("sth");
obj.getClass().getClassLoader().getResource("sth");
obj.getClass().getClassLoader().getSystemClassLoader().getResource("sth");
My.class.getClass().getClassLoader().getSystemClassLoader().getResource("sth");

Я правильно понимаю:

1) На любом сервере приложений (включая Tomcat) я буду использовать только Thread.currentThread().getContextClassLoader().getResourceAsStream("NoSlash!_Img.png");

1.1) Я никогда не буду использовать все остальное (на любом сервере приложений)

2) В настольном приложении все вышеперечисленное эквивалентно

3) Сам Tomcat (класс, содержащий main () - точку входа Tomcat) загружается с помощью загрузчика системного класса, который всегда (100%?) Можно идентифицировать с помощью ClassLoader.getSystemClassLoader()

Что такое System.setProperty("java.system.class.loader"), мне непонятно. Кроме того, obj.getClass().getClassLoader().getSystemClassLoader() также должен возвращать то же самое, что и ClassLoader.getSystemClassLoader(), но может возвращать null (если разработчик пользовательского загрузчика классов решит, что им лучше не раскрывать системный загрузчик классов). Кроме нуля и реального System ClassLoader obj.getClass().getClassLoader().getSystemClassLoader() может не возвращать ничего другого (потому что возвращать какой-то другой загрузчик классов было бы глупо?).

4) Любое веб-приложение (= context = WAR) в Tomcat / другом сервере приложений загружается с помощью своего индивидуального (настраиваемого) загрузчика классов (иногда называемого «загрузчиком классов приложения», что путает его с «загрузчиком системного класса», иногда также называемым « загрузчик классов приложения "). Если я нахожусь в методе класса A, вызов this.getClass().getClassLoader() дает мне (настраиваемый) загрузчик классов, который загрузил мой класс A (и всю мою WAR / приложение).

Так почему я должен использовать Thread.currentThread().getContextClassLoader().getResource("sth") вместо this.getClass().getClassLoader().getResource("sth")? Я подумал, что лучше всего использовать собственный загрузчик классов WAR!

Всегда ли загрузчик классов контекста одинаков во всех потоках моей WAR (если я сам не запускаю потоки и не связываюсь с загрузчиками классов контекста) и такой же, как пользовательский загрузчик классов, который загрузил мою WAR (objOfMyOwnClassesCreatedAnywhereWithinMyApp.getClass().getClassLoader())?

Изучены ссылки: this, это, это

P.S. здесь подразумевает одну ситуацию, в которой я предпочитаю используя контекстный загрузчик классов. Это означает, что можно не использовать загрузчик класса контекста во многих других ситуациях (когда объект, созданный в моем потоке, не передается ни одному другому потоку, особенно такому другому потоку, который не был создан мной).

Каждый класс будет использовать свой собственный загрузчик классов для загрузки других классов. Поэтому, если ClassA.class ссылается на ClassB.class, тогда ClassB должен находиться в пути к классам загрузчика классов ClassA или его родителей.

Загрузчик классов контекста потока - это текущий загрузчик классов для текущего потока. Объект может быть создан из класса в ClassLoaderC, а затем передан в поток, принадлежащий ClassLoaderD. В этом случае объект должен использовать Thread.currentThread (). getContextClassLoader () напрямую i < em> f он хочет загрузить ресурсы, недоступные в его собственном загрузчике классов.

Помимо Stackoverflow answer здесь (@yonran) рекомендует:

никогда не используйте загрузчик классов контекста!


person Code Complete    schedule 04.01.2019    source источник
comment
На самом деле все это неверно. java.lang.Class имеет собственные методы getResource и getResourceAsStream, и это то, что вам следует использовать: My.class.getResource("data.bin") Обратите внимание, что, в отличие от ClassLoader.getResource, Class.getResource ищет ресурсы относительно пакета класса. Это преднамеренный дизайн; вы всегда должны размещать ресурсы в пакетах, чтобы предотвратить возможное столкновение с другими библиотеками. (Вы же не стали бы хранить файлы в корневом каталоге жесткого диска, верно?)   -  person VGR    schedule 04.01.2019