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

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

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

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

Принимая это во внимание, я внес соответствующие изменения в свой проект. Вот мой 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>

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

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();

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

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

ContextProvider.get<PropertyName>;

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

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

Примечание. Что касается других вопросов, отмеченных выше

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


person srk    schedule 27.02.2013    source источник
comment
Вы используете Spring MVC или пытаетесь использовать базовые сервлеты?   -  person Niall Thomson    schedule 27.02.2013
comment
Я не использую Spring MVC, просто использую его для IOC   -  person srk    schedule 27.02.2013
comment
В общем, кому-то понадобится получить bean-компонент из ApplicationContext. В идеале он будет вызываться только один раз, и это будет объект начальной загрузки ...   -  person nicholas.hauschild    schedule 27.02.2013


Ответы (2)


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

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

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

Итак, да, инъекции, и нет статике.

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

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

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

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

person Jimadilo    schedule 27.02.2013
comment
В своей компании я никогда не видел ApplicationContext.getBean() и прочее. Но это потому, что это веб-приложения корпоративного уровня. Так что именно загружает для меня все мои занятия? Это делает сервер? - person Kraken; 07.05.2014
comment
Обычно вы используете один из заранее подготовленных классов загрузки приложения Spring, которые являются стандартными компонентами JEE, такими как сервлеты и тому подобное. Затем они запускают все весенние работы с МОК. Спрятанный в недрах этих классов, будет вызов для создания контекста приложения из XML-файла, связывания его с текущим запущенным приложением и предоставления доступа к контексту приложения. - person Jimadilo; 09.06.2014

Вот мой пример получения первого экземпляра без фактического вызова 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();
  }
}
person rIshab1988    schedule 11.08.2014