Подтвердить что ты не робот

Как избежать использования ApplicationContext.getBean() при реализации Spring IOC

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

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello"); 

Как ссылка на эти вопросы 1 и 2 в stackoverflow. Я предположил, что нет необходимости использовать appContext.getBean( "hello" ) в коде, который считается плохой практикой. Кроме того, больше не рекомендуется. Исправьте меня прямо здесь, если мои выводы ошибочны.

Учитывая это, я внес изменения в свой проект. Здесь мой applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
   <property name="utils" ref="utilClassRef" />
</bean>
</beans>

Мой код класса CodeProvider

public class ContextProvider implements ApplicationContextAware {

    private static ApplicationContext ctx;

    /**
     * Objects as properties
     */
    private static DUtils utils;

    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

    public static DUtils getUtils() {
        return utils;
    }

    public void setUtils(DUtils dUtilsRef) {
        utils = dUtilsRef;
    }

}

Например, рассмотрим класс A, который зависит от org.hd.derbyops.DUtils. Я использую следующую строку кода

ContextProvider.getUtils();

inorder, чтобы получить объект DUtils в классе A, тем самым избегая использования ApplicationContext.getBean() в любом месте моего кода.

Предположим, что если у меня есть 10 классов, а мой класс A зависит от всех из них, чьи объекты должны быть созданы и доступны без использования ApplicationContext.getBean(). В этом случае, как было сделано выше, я подумал о создании свойств класса ContextProvider, за которыми следуют setter и getter этого свойства, где в get<PropertyName> статично. Таким образом, я могу использовать его везде, где мне нужен объект, вроде этого

ContextProvider.get<PropertyName>;

Вот мой краткий вопрос. Во-первых, верно ли мой подход? Если это так, загрузите все beans при запуске, не будет ли это убийцей производительности? Как бы вы это делали в своих приложениях, не вызывая getBean по крайней мере один раз?

Если вы должны были создать веб-приложение, и вы должны были реализовать Spring IOC, не используя ApplicationContext.getBean() в любом из кода. Как бы Вы это сделали?

Примечание: со ссылкой на другие теги, отмеченные выше

Вызов ApplicationContext.getBean() не является инверсией управления!

4b9b3361

Ответ 1

Простые ответы да и нет, нет и нет. И, наконец, выполните поиск в Интернете для spring MVC, так как это, вероятно, делает то, что вы хотите.

Итак, ваш подход. Да, у вас есть все в порядке. Тем не менее, он считает очень плохую практику использовать статические методы для всего. И вам это не нужно. spring основывается на идее, что вы можете просто создать нормальные pojos, а spring будет использовать их в виде синглонов и вставлять их друг в друга (он также может создавать объекты "на лету", но я собираюсь случай здесь). Если вы используете статические классы и методы, то:

  • Вы не можете имитировать их для модульного тестирования (вы используете JUnit правильно?)
  • Вы не можете использовать их с наследованием
  • Статические инициализаторы - отличный способ избавиться от исключений
  • и т.д.

Итак, да, для инъекций, а не для статического материала.

Далее, производительность. Вы правы в том, что гораздо медленнее использовать spring, но если вы делаете всю свою инъекцию при запуске, это происходит только один раз. spring предназначен для приложений на стороне сервера, где, вероятно, будет несколько одноэлементных классов, передающих данные. Таким образом, может быть класс, чтобы получить материал из БД, один для его обработки, и один для его отображения, а spring используется для их соединения.

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

Наконец, если вы просто вводите все зависимости для класса в него при запуске, и вы делаете это со всеми вашими классами, вам вообще не нужно делать какие-либо материалы getBean. Кроме того, использование атрибутов init-method и destroy-method в bean означает, что вы можете запускать процессы после того, как spring завершил впрыскивание зависимостей. Вам нужно загрузить только контекст, и ваше приложение будет spring (каламбур).

Что касается веб-проектов, spring MVC в основном принимает всю инверсию шаблона управления и применяет его к веб-приложениям. Содержимое spring загружается контейнером, и вы можете определить URL-адреса для ответа на использование не более чем bean имен. И большая часть вашего кода может оставаться как pojos. Если у вас есть что-то безумно сложное, вы можете посмотреть веб-поток spring, но я бы посоветовал вам убедиться, что ваш spring foo очень силен, прежде чем пытаться это сделать.

Ответ 2

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

public class Test{
  // Declare private static variable so that we can access it in main()
  private static Triangle triangle;

  // Use constructor injection to set the triangle
  public Test(Triangle triangle) {
      Test.triangle = triangle;
  }

  public static void main(String[] args) {
      // Specify the context file containing the bean definitions
      // Spring automatically creates instances of all the beans defined
      // in this XML file. This process is performed before you actually make
      // a getBean("beanName") call.
      ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

      // Use instance methods of triangle 
      Test.triangle.draw();
  }
} 

Вы можете использовать другой способ:

В spring.xml (ваш XML файл конфигурации bean)

<bean class="com.example.Test" init-method="myMethod">
    <constructor-args ref="triangle"/>
</bean>

Теперь для вашего основного класса

public class Test {
  private final Triangle triangle;

  public Test (Triangle triangle) {
     this.triangle = triangle;
  }

  public static void main (String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
  }

  // Called by Spring immediately after the Triangle Bean has been created and
  // all the properties for the bean have been set. This method name must match
  // the one specified with destroy-method attribute in spring.xml
  public void myMethod () {
     triangle.draw();
  }
}