getSystemResource () против getResource () с соответствующим ClassLoader - PullRequest
0 голосов
/ 04 января 2019

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

Является ли 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");

против

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

против

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). Кроме нулевого и реального 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())?

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

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

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

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

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

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

...