2014-09-24 7 views
13

Ich muss Prototyp-Klasse von Singleton bekommen. Ich fand, dass die Methode Injektion ist der Weg zu gehen, aber ich weiß nicht wirklich, wie man Spring @ Lookup Annotation verwenden.Wie benutzt man Spring @ Lookup Annotation?

Ich bin neu in Abhängigkeit-Injektion, und ich entschied mich, mit Annotation-Konfiguration zu gehen, also möchte ich in dieser Richtung fortsetzen.

Ich fand heraus, dass @Lookup Annotation erst kürzlich hinzugefügt wurde (https://spring.io/blog/2014/09/04/spring-framework-4-1-ga-is-here), aber ich kann nirgendwo finden, wie man es benutzt.

So, hier ist, vereinfachtes Beispiel

Konfigurationsklasse:

@Configuration 
@Lazy 
public class ApplicationConfiguration implements ApplicationConfigurationInterface { 

    @Bean 
    public MyClass1 myClass1() { 
    return new ContentHolderTabPaneController(); 
    } 

    @Bean 
    @Scope("prototype") 
    public MyClass2 myClass2() { 
    return new SidebarQuickMenuController(); 
    } 
} 

Und hier ist Klasse Beispiel:

public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    public MyClass2 myClass2(){ 
    } 
} 

Wie mache ich das mit @Lookup Anmerkung?

Antwort

24

Bevor @Lookup Anmerkung zu Ihrem public MyClass2 myClass2() Methode anwenden, lesen Sie in @Lookup's Javadoc:

der Container Laufzeit Subklassen der Methode der enthaltenden Klasse über CGLIB erzeugen, weshalb solche Lookup-Methoden nur auf Bohnen arbeiten können, dass Der Container wird durch reguläre Konstruktoren instanziiert (dh Suchmethoden können nicht auf Bohnen ersetzt werden, die von den Factory-Methoden zurückgegeben werden, wo wir für sie keine dynamische Unterklasse bereitstellen können).

So entfernen Sie die folgende Factory-Methode Stil Bohne Erklärung von ApplicationConfiguration:

@Bean 
    public MyClass1 myClass1() { 
    return new ContentHolderTabPaneController(); 
    } 

und fügen @Component Anmerkung lassen Frühling die Bean instanziiert (auch fügen Sie die @Lookup Anmerkung zur Methode):

@Component 
public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    @Lookup 
    public MyClass2 myClass2(){ 
    return null; // This implementation will be overridden by dynamically generated subclass 
    } 
} 

Jetzt myClass1 Bean aus dem Zusammenhang geraten, und seine myClass2 Methode sollte ersetzt/überschrieben werden n, um jedes Mal eine neue Prototyp-Bean zu erhalten.


aktualisieren:

Mit Factory-Methode Erklärung

Es ist nicht schwer, die @Lookup kommentierten Methode (die "Lookup-Methode") zu implementieren. Ohne @Lookup und Ihre Konfigurationsklasse unverändert zu halten, jetzt MyClass1 sieht aus wie (in der Tat Frühling eine ähnliche Implementierung in einer Unterklasse erzeugt, wenn @Lookup verwendet wurden):

public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    @Autowired 
    private ApplicationContext applicationContext; 
    public MyClass2 myClass2() { 
     return applicationContext.getBean(MyClass2.class); 
    } 
} 

Frühling die ApplicationContext für Sie einspritzt.

+0

Vielen Dank. Und gibt es eine Möglichkeit, das MyClass1 Bean in einer Factory-Stil-Bean-Deklaration als Abhängigkeit zu verwenden? – Miljac

+0

Dann implementieren wir unsere eigene Lookup-Methode - zum Glück ist es sehr einfach. Siehe mein Update zur Antwort. – qingbo

+3

Aber ist das nicht die Absicht, DI zu vereiteln, weil Bean eigentlich auf den DI-Container achten muss? – Miljac

5

Wenn Sie nicht auf Frühling 4 sind.1 können Sie den Anbieter Injektion anstelle:

public class MyClass1 { 
    @Autowired 
    private Provider<MyClass2> myClass2Provider; 

    doSomething() { 
    MyClass2 myClass2 = myClass2(); 
    myClass2.fooBar() 
    } 

    public MyClass2 myClass2(){ 
    return myClass2Provider.get(); 
    } 
} 

Dies ist DI, IoC, vermeidet abstrakte Klassen und XML-Definitionen für Lookup-Methoden.

+3

'javax.inject.Provider ', um genau zu sein – alaster

+0

Das hat gut funktioniert in meinem Unit-Tests. Ich konnte @Lookup nicht zur Arbeit bringen – rince