Почему ApplicationContext.getBean Spring считают плохим?

2,147,483,647 - это значение для Integer.MAX_VALUE

2,304,438,636 слишком большое, чтобы содержаться в переменной Integer

Используйте Long вместо своих идентификаторов в целом , Или, что еще лучше, примитив long, поскольку в идеале ваши идентификаторы никогда не должны быть null

261
задан Community 23 May 2017 в 02:26
поделиться

9 ответов

Я упоминал об этом в комментарии к другому вопросу, но вся идея Инверсии Контроля состоит в том, чтобы ни один из ваших классов не знал или не заботился как они получают объекты, от которых зависят . Это позволяет легко изменить тип реализации данной зависимости, которую вы используете в любое время. Это также облегчает тестирование классов, поскольку вы можете предоставить имитационные реализации зависимостей. Наконец, это делает классы более простыми и более сосредоточенными на их основной ответственности.

Вызов ApplicationContext.getBean () не является инверсией управления! Хотя все еще легко изменить, какая реализация настроена для данного имени компонента, теперь класс напрямую полагается на Spring для обеспечения этой зависимости и не может получить ее другим способом. Вы не можете просто сделать свою собственную ложную реализацию в тестовом классе и передать ее себе. Это в основном противоречит цели Spring как контейнера для внедрения зависимостей.

Везде, где вы хотите сказать:

MyClass myClass = applicationContext.getBean("myClass");

вместо этого вы должны, например, объявить метод:

public void setMyClass(MyClass myClass) {
   this.myClass = myClass;
}

И затем в вашей конфигурации:

<bean id="myClass" class="MyClass">...</bean>

<bean id="myOtherClass" class="MyOtherClass">
   <property name="myClass" ref="myClass"/>
</bean>

Spring будет автоматически вставьте myClass в myOtherClass .

Объявите все таким образом, и в корне этого есть что-то вроде:

<bean id="myApplication" class="MyApplication">
   <property name="myCentralClass" ref="myCentralClass"/>
   <property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>

MyApplication - самый центральный класс, и, по крайней мере, косвенно зависит от любой другой службы в вашей программе. При начальной загрузке в вашем основном методе вы можете вызвать applicationContext.getBean ("

199
ответ дан 23 November 2019 в 02:36
поделиться

Другие указали на общую проблему (и являются правильными ответами), но я просто предложу еще один комментарий: это не то, что вы НИКОГДА не должны делать это, а скорее делать это как можно меньше насколько это возможно.

Обычно это означает, что это делается ровно один раз: во время начальной загрузки. И тогда это просто доступ к «корневому» бину, через который могут быть разрешены другие зависимости. Это может быть повторно используемый код, например базовый сервлет (при разработке веб-приложений).

4
ответ дан 23 November 2019 в 02:36
поделиться

Мотивация - написать код, который явно не зависит от Spring. Таким образом, если вы решите переключать контейнеры, вам не нужно переписывать какой-либо код.

Думайте о контейнере как о чем-то невидимом для вашего кода, волшебном обеспечении его потребностей, без запроса.

Внедрение зависимости является контрапунктом к шаблону «поиск сервисов». Если вы собираетесь искать зависимости по имени, вы можете также избавиться от контейнера DI и использовать что-то вроде JNDI.

16
ответ дан 23 November 2019 в 02:36
поделиться

Идея состоит в том, что вы полагаетесь на внедрение зависимостей ( инверсия управления или IoC). То есть ваши компоненты настроены так, как им нужно. Эти зависимости вставляются в (через конструктор или установщики) - тогда вы не получите их сами.

ApplicationContext.getBean () требует, чтобы вы явно указали имя компонента в вашем компоненте. Вместо этого, используя IoC, ваша конфигурация может определить, какой компонент будет использоваться.

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

4
ответ дан 23 November 2019 в 02:36
поделиться

Одним из самых классных преимуществ использования чего-то вроде Spring является то, что вам не нужно соединять свои объекты вместе. Голова Зевса распадается, и ваши классы появляются полностью сформированными со всеми зависимостями, созданными и подключенными по мере необходимости. Это волшебно и фантастично.

Чем больше вы говорите ClassINeed classINeed = (ClassINeed) ApplicationContext.getBean ("classINeed"); , тем меньше магии вы получаете. Меньше кода почти всегда лучше. Если вашему классу действительно нужен компонент ClassINeed, почему вы просто не подключили его?

Тем не менее, очевидно, что для создания первого объекта нужно что-то. В вашем основном методе нет ничего плохого в том, чтобы получить один или два компонента с помощью getBean (), но вам следует избегать этого, потому что всякий раз, когда вы его используете, вы '

21
ответ дан 23 November 2019 в 02:36
поделиться

Я обнаружил только две ситуации, в которых требовался getBean ():

Другие упоминали об использовании getBean () в main () для выборки «основного» bean-компонента для отдельной программы.

Другое использование getBean (), которое я использовал, - в ситуациях, когда интерактивная конфигурация пользователя определяет структуру bean-компонента для конкретной ситуации. Так, например, часть загрузочной системы проходит по таблице базы данных, используя getBean () с определением компонента scope = 'prototype', а затем устанавливает дополнительные свойства. Предположительно, существует пользовательский интерфейс, который настраивает таблицу базы данных, что было бы более удобным, чем попытка (пере) переписать контекст приложения XML.

3
ответ дан 23 November 2019 в 02:36
поделиться

One of Spring premises is avoid coupling. Define and use Interfaces, DI, AOP and avoid using ApplicationContext.getBean() :-)

4
ответ дан 23 November 2019 в 02:36
поделиться

Это правда, что включение класса в application-context.xml избавляет от необходимости использовать getBean. Однако даже в этом нет необходимости. Если вы пишете автономное приложение и НЕ ДЕЛАЕТЕ Я хочу включить свой класс драйвера в application-context.xml, вы можете использовать следующий код, чтобы Spring автоматически подключала зависимости драйвера:

public class AutowireThisDriver {

    private MySpringBean mySpringBean;    

    public static void main(String[] args) {
       AutowireThisDriver atd = new AutowireThisDriver(); //get instance

       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                  "/WEB-INF/applicationContext.xml"); //get Spring context 

       //the magic: auto-wire the instance with all its dependencies:
       ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
                  AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);        

       // code that uses mySpringBean ...
       mySpringBean.doStuff() // no need to instantiate - thanks to Spring
    }

    public void setMySpringBean(MySpringBean bean) {
       this.mySpringBean = bean;    
    }
}

Мне приходилось делать это пару раз, когда у меня был какой-то отдельный класс который должен использовать какой-то аспект моего приложения (например, для тестирования), но я не хочу включать его в контекст приложения, потому что он фактически не является частью приложения. Также обратите внимание, что это избавляет от необходимости искать bean-компонент по строковому имени, которое я всегда считал некрасивым.

Я не хочу включать его в контекст приложения, потому что на самом деле он не является частью приложения. Также обратите внимание, что это избавляет от необходимости искать bean-компонент по строковому имени, которое я всегда считал некрасивым.

Я не хочу включать его в контекст приложения, потому что на самом деле он не является частью приложения. Также обратите внимание, что это избавляет от необходимости искать bean-компонент по строковому имени, которое я всегда считал некрасивым.

25
ответ дан 23 November 2019 в 02:36
поделиться

Причины, по которым следует предпочесть Service Locator инверсии управления (IoC):

  1. Service Locator намного проще для других людей следовать в вашем коде. IoC - это волшебство но программисты обслуживания должны понимать ваши запутанные конфигурации Spring и все бесчисленное множество мест, чтобы выяснить, как вы связали свои объекты.

  2. IoC ужасен для отладки проблем конфигурации. В некоторых классах приложений приложение не запускается при неправильной настройке, и у вас может не быть возможности пройти через то, что происходит с отладчиком.

  3. IoC в основном основан на XML (аннотации улучшают ситуацию, но все еще много XML там). Это означает, что разработчики не могут работать с вашей программой, если они не знают все волшебные теги, определенные Spring. Знать Java уже недостаточно. Это мешает программистам с меньшим опытом (т. Е. На самом деле использование более сложного решения является плохой конструкцией, если более простое решение, такое как Service Locator, будет удовлетворять тем же требованиям). Плюс, поддержка диагностики проблем XML намного слабее, чем поддержка проблем Java.

  4. Внедрение зависимостей больше подходит для более крупных программ. В большинстве случаев дополнительная сложность того не стоит.

  5. Часто Spring используется в случае, если вы «можете захотеть изменить реализацию позже». Есть и другие способы достижения этого без сложности Spring IoC.

  6. Для веб-приложений (Java EE WARs) контекст Spring эффективно связывается во время компиляции (если вы не хотите, чтобы операторы копались в контексте в развернутой войне). Вы можете заставить Spring использовать файлы свойств, но с сервлетами файлы свойств должны находиться в заранее определенном месте, что означает, что вы не можете развернуть несколько сервлетов одновременно в одном и том же блоке. Вы можете использовать Spring с JNDI для изменения свойств во время запуска сервлета, но если вы используете JNDI для параметров, изменяемых администратором, потребность в самой Spring уменьшается (поскольку JNDI фактически является локатором служб).

  7. С помощью Spring вы можете потерять контроль над программой, если Spring отправляет ваши методы. Это удобно и работает для многих типов приложений, но не для всех. Вам может потребоваться управлять потоком программы, когда вам нужно создать задачи (потоки и т. Д.) Во время инициализации или вам понадобятся изменяемые ресурсы, о которых Spring не знал, когда контент был привязан к вашей WAR.

Spring очень хорош для управления транзакциями и имеет ряд преимуществ. Просто IoC может быть чрезмерным во многих ситуациях и привносит неоправданную сложность для сопровождающих. Не используйте IoC автоматически, не подумав сначала о том, как не использовать его.

  • Используя Spring, вы можете потерять управление программой, если Spring отправляет ваши методы. Это удобно и работает для многих типов приложений, но не для всех. Вам может потребоваться управлять потоком программы, когда вам нужно создать задачи (потоки и т. Д.) Во время инициализации или если вам нужны изменяемые ресурсы, о которых Spring не знал, когда контент был привязан к вашей WAR.

  • Spring очень хорош для управления транзакциями и имеет ряд преимуществ. Просто IoC может быть чрезмерным во многих ситуациях и привносить неоправданную сложность для сопровождающих. Не используйте IoC автоматически, не подумав о том, как сначала не использовать его.

  • С помощью Spring вы можете потерять управление программой, если Spring отправляет ваши методы. Это удобно и работает для многих типов приложений, но не для всех. Вам может потребоваться управлять потоком программы, когда вам нужно создать задачи (потоки и т. Д.) Во время инициализации или если вам нужны изменяемые ресурсы, о которых Spring не знал, когда контент был привязан к вашей WAR.

  • Spring очень хорош для управления транзакциями и имеет ряд преимуществ. Просто IoC может быть чрезмерным во многих ситуациях и привносить неоправданную сложность для сопровождающих. Не используйте IoC автоматически, не подумав о том, как сначала не использовать его.

    Вам может потребоваться управлять потоком программы, когда вам нужно создать задачи (потоки и т. Д.) Во время инициализации или если вам нужны изменяемые ресурсы, о которых Spring не знал, когда контент был привязан к вашей WAR.

    Spring очень хорош для управления транзакциями и имеет ряд преимуществ. Просто IoC может быть чрезмерным во многих ситуациях и привносит неоправданную сложность для сопровождающих. Не используйте IoC автоматически, не подумав о том, как сначала не использовать его.

    Вам может потребоваться управлять потоком программы, когда вам нужно создать задачи (потоки и т. Д.) Во время инициализации или если вам нужны изменяемые ресурсы, о которых Spring не знал, когда контент был привязан к вашей WAR.

    Spring очень хорош для управления транзакциями и имеет ряд преимуществ. Просто IoC может быть чрезмерным во многих ситуациях и привносит неоправданную сложность для сопровождающих. Не используйте IoC автоматически, не подумав сначала о том, как не использовать его.

    64
    ответ дан 23 November 2019 в 02:36
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: