wake-up-neo.net

So vermeiden Sie die Verwendung von ApplicationContext.getBean () bei der Implementierung von Spring IOC

Ich fange gerade erst mit dem Konzept von Spring IOC an. Ich sehe oft, dass die meisten Beispiele im Internet den Code verwenden, um das Objekt zu erhalten.

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

Als Referenz aus diesen Fragen 1 und 2 im Stackoverflow. Ich habe daraus geschlossen, dass es nicht notwendig ist, appContext.getBean ("Hallo") im Code zu verwenden, was als schlechte Praxis betrachtet wird. Auch nicht mehr zu empfehlen. Korrigiere mich hier, wenn meine Schlussfolgerung falsch ist. 

Um dies im Blick zu behalten, habe ich entsprechend Änderungen in meinem Projekt vorgenommen. Hier ist meine 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>

Mein classProvider-Klassencode

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;
    }

}

Betrachten Sie beispielsweise eine Klasse A, die von org.hd.derbyops.DUtils abhängt. Ich verwende die folgende Codezeile

ContextProvider.getUtils();

um DUtils Object in Klasse A zu bekommen, um ApplicationContext.getBean() an keiner Stelle in meinem Code zu verwenden.

Angenommen, ich habe 10 Klassen und meine Klasse A ist von allen abhängig, deren Objekte erstellt werden sollen und ohne ApplicationContext.getBean() darauf zuzugreifen ist. In diesem Fall denke ich auch daran, Eigenschaften der ContextProvider-Klasse zu erstellen, gefolgt von Setter und Getter dieser Eigenschaft, wobei get<PropertyName> statisch ist. Ich kann es also überall dort einsetzen, wo ich ein Objekt wie dieses brauche

ContextProvider.get<PropertyName>;

Hier ist meine kurze Frage. Erstens, ist mein Ansatz richtig? Wenn es richtig ist, alle Beans beim Start zu laden, wäre das nicht ein Performancekiller? Wie würden Sie das in Ihren Anwendungen tun, ohne getBean atleast mehr als einmal aufzurufen?

Wenn Sie eine Webanwendung entwerfen und Spring IOC implementieren, ohne ApplicationContext.getBean() in einem der Codes zu verwenden. Wie würdest du das machen? 

Hinweis: mit Bezug auf die anderen oben markierten Fragen 

Das Aufrufen von ApplicationContext.getBean () ist keine Inversion des Steuerelements!

12
srk

Die einfachen Antworten sind ja und nein, nein und nein. Und schließlich können Sie online nach Spring MVC suchen, da dies wahrscheinlich das tut, was Sie möchten.

Also dein Ansatz. Ja, du hast das meiste richtig. Es wird jedoch als sehr schlechte Praxis angesehen, für alles statische Methoden zu verwenden. Und das musst du nicht. Der Frühling basiert auf der Idee, dass Sie ganz einfach normale Pojos erstellen können, und der Frühling verwendet sie als Singletons und injiziert sie ineinander (er kann auch Objekte im Fluge erstellen, aber ich wende mich hier für den üblichen Fall). Wenn Sie statische Klassen und Methoden verwenden, gilt Folgendes:

  • Sie können sie nicht für Unit-Tests verspotten (Sie verwenden JUnit, richtig?)
  • Sie können sie nicht mit Vererbung verwenden
  • Statische Initialisierer sind eine großartige Möglichkeit, Ausnahmen zu verlieren
  • usw usw

Also ja zur Injektion und nein zum statischen Zeug.

Als nächstes Leistung. Sie haben Recht, es ist viel langsamer, den Frühling zu verwenden, aber wenn Sie beim Start alle Injektionen durchführen, geschieht dies nur einmal. Spring ist für serverseitige Anwendungen gedacht, bei denen wahrscheinlich mehrere Singleton-Klassen Daten weitergeben. Es kann also eine Klasse geben, die Daten aus einer Datenbank abruft, eine, die sie verarbeitet, und eine, um sie anzuzeigen, und es wird eine Feder verwendet, um sie miteinander zu verbinden.

Wenn Sie spring in einer Anwendung verwenden, in der Sie wiederholt starten, wie z. B. einer Befehlszeilen-App, dann verwenden Sie sie für die falsche Art von Anwendung und möchten möglicherweise einen Builder oder etwas anderes verwenden. Spring ist für große Unternehmensanwendungen gedacht, die nicht häufig neu gestartet werden.

Wenn Sie beim Start einfach alle Abhängigkeiten für eine Klasse in die Klasse einfügen und dies mit all Ihren Klassen tun, müssen Sie überhaupt keine getBean-Sachen machen. Die Verwendung der Attribute init-method und destroy-method für ein Bean bedeutet auch, dass Sie Prozesse starten können, sobald der Frühling das Einfügen von Abhängigkeiten abgeschlossen hat. Sie müssen nur den Kontext laden und Ihre App wird (Wortspiel beabsichtigt) ins Leben gerufen.

Bei Webprojekten übernimmt Spring MVC grundsätzlich die gesamte Inversion des Kontrollmusters und wendet es auf Webanwendungen an. Das Frühlingsmaterial wird vom Container geladen, und Sie können die URLs definieren, auf die Sie antworten möchten, und verwenden dabei lediglich Bean-Namen. Und der größte Teil Ihres Codes kann als Pojos bleiben. Wenn Sie etwas Wahnsinnig Komplexes haben, möchten Sie vielleicht den Bahnfluss des Frühlings betrachten, aber ich würde Ihnen raten, sich zu vergewissern, dass Ihr Frühlings-Foo sehr stark ist, bevor Sie dies versuchen.

9
Jimadilo

Hier ist mein Beispiel, um die erste Instanz abzurufen, ohne getBean() für ApplicationContext aufzurufen.

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

Sie können einen anderen Weg verwenden:

In spring.xml (Ihre Bean-Konfigurations-XML-Datei)

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

Jetzt für deine Hauptklasse

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();
  }
}
1
rIshab1988