# Factory und Spring



## Gast2 (29. Mai 2010)

Hallo,

ich bin mir nicht sicher ob das eine gute Lösung ist, aber ich beschreib mal was ich vor hab.
Ich wollte eine Factory machen die mir Objekte erzeugt und die ich dann meiner spring.xml bekannt mache und dann mit @Autowired an bestimmte Stellen injezieren lasse. 
Zu meinem Problem: Die Factory gibt es einmal, jetzt hab ich eine create methode z.b

```
public X createX(){
 return XImpl();
}
```
X ist auch eine Spring Bean.
jetzt will ich aber hier nicht die konkrete implmentierung angeben sondern, das XImpl mit Spring jedes mal neu erzeugen lassen. Wie kann ich das machen? Ich möchte ungern über den context die bean auslesen.
Kann man sowas machen wie

```
@Autowired
private X x;

public X createX(){
 return x;
}
```
und jedes mal wenn die Methode aufgerufen wird, wird ein neues X mit der in Spring angebene Implementierung erzeugt??Geht sowas?????????:L
Oder wie macht man sowas besser?

Gruß


----------



## Gast2 (2. Jun 2010)

Keiner eine Idee?


----------



## Noctarius (2. Jun 2010)

Implementiere das Interface FactoryBean und setze isSingletion() == false

Zum Nutzen des FactoryBean setzt du im AppContext.xml statt der zu instanzierenden Klasse die FactoryBean implementierende Klasse ein.

Willst du also FooImpl instanzieren (injecten) lassen setzt du FooFactory implements FactoryBean stattdessen ein.


PS: Steht aber auch alles dick und breit in der Spring Dokumentation (Chapter3.The IoC container) und wer mit Spring arbeiten will für den ist die Spring Doku Pflichtlektüre!


----------



## Gast2 (2. Jun 2010)

Entweder has du mich falsch verstanden oder ich checks grad net^^...
Werds mir nochmal druchlesen, hab dazu aber letztes mal nichts gefunden...


----------



## Gast2 (3. Jun 2010)

Also ich hatte jetzt sowas hier vor:

```
public class FooFactory implements FactoryBean<FooIF>{

	@Autowired
	private FooIF foo;
	
	@Override
	public GameObjectModel getObject() throws Exception {
                // oder aber würde ich nicht wollen return new FooImpl();

		return foo;
	}

	@Override
	public Class<?> getObjectType() {
		return FooIF.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}
	
}
```

Aber so bekomme ich ja die gleiche Instanz zurück anstatt eine neue, also hat sich ja nichts verändert
Weil ich hab einen Handler der wird nur einmal instanziert. Und wie bekomme ich nun aus der Factory immer wieder eine neue Instanz?

```
public class FoorHandler extends AbstractHandler{

	@Autowired
	private FooFactory factory;
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {	
			try {
				System.out.println(factory.getObject());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		return null;
	}

}
```
...


----------



## Noctarius (4. Jun 2010)

Du gibst doch auch immer das Selbe Objekt aus der Factory heraus, was erwartest du denn? OO

Grundlagen: Setzen, Sechs ^^


----------



## Gast2 (4. Jun 2010)

Noctarius hat gesagt.:


> Du gibst doch auch immer das Selbe Objekt aus der Factory heraus, was erwartest du denn? OO
> 
> Grundlagen: Setzen, Sechs ^^



Das weiß ich !!!!!!!!!!!!!!!!!! 
Genau das ist ja mein Problem , wie man das machen kann darum hab ich ja die Kommentare dazu gemacht, dass ich es so machen könnte.
Und ich wollte wissen ob es eine Möglichkeit mit Spring gibt immer eine neue Instanz zu bekommen ohne dass man die Impl zurückgibt oder auf context.getBean zurückgreifen muss


----------



## Noctarius (4. Jun 2010)

Ich versteh nicht was du willst oder es ist so sinnfrei, dass ich es nicht verstehen will. Entweder du willst immer eine neue Instanz dann machst du in getObject eben new Foo() oder du keine Ahnung was du willst.


----------



## Gast2 (4. Jun 2010)

Ja ich will immer eine neue Instanz, vielleicht hab ich auch das Prinzip der FactoryBean nicht ganz verstanden.

Beispiel: Interface Foo. 2 Implmentierungen: Foo1Impl, Foo2Impl
Jetzt wollte ich eigentlich über die Factory immer neue Instanzen zurückbekommen, je nachdem was ich im Spring context.xml eingepflegt habe.

Oder mache ich dafür dann 2 Factory?

Jetzt verständlicher was ich vor habe?^^


----------



## Noctarius (4. Jun 2010)

Entweder gibst du der Factory Bean über eine eigene Property die zu instanzierende Klasse mit oder du machst halt ne zweite Factory Bean. Klar ist mir die Frage immer noch nicht oder du hast das Prinzip nicht verstanden Oo


----------



## Gast2 (4. Jun 2010)

Also ich versuchs nochmal zu erklären ... 
Ich hab einen Handler der einmal instanziert wird, der soll eine Factory injecten, soweit gut. 
Die Factory soll neue Objekte zurück geben, aber in dieser Factory will ich nicht(falls das geht) die dirkete implmentierung angeben. Wie würdest du denn es machen, vielleicht check ich es dann Oo...
Also Interface Foo, Implementierung Foo1Impl, Foo2Impl... Wie würde dann die Factory aussehen?


----------



## mvitz (4. Jun 2010)

Ohne Experte in Spring zu sein, gibts hier meiner Meinung nach zwei Möglichkeiten.

1) Du greifst in der FooFactory direkt auf den Spring Applikation Context zu und lädst eine Bean, die einen Prototpye Scope besitzt.

2) Du baust eine weitere Abstraktion ein.


```
public interface FooIFFactory {
  FooIF getNewInstance();
  Class<? extends FooIF> getInstanceClass();
```




```
public class FooFactory implements FactoryBean<FooIF>{
 
    @Autowired
    private FooIFFactory foo;
    
    @Override
    public GameObjectModel getObject() throws Exception {
                // oder aber würde ich nicht wollen return new FooImpl();
 
        return foo.getNewInstance();
    }
 
    @Override
    public Class<?> getObjectType() {
        return foo.getInstanceClass();
    }
 
    @Override
    public boolean isSingleton() {
        return false;
    }
    
}
```

Dann kannst du für jede FooIF Implementierung eine eigenen FooIFFactory Implementierung schreiben.


----------



## Gast2 (5. Jun 2010)

Also zu Punkt 1 wie gesagt wollte nicht auf den Context zugreifen...
Punkt 2 werd ich mal versuchen ...
Was sagt der Spring Experte dazu? Ist sowas okay oder gibt es einen anderen (besseren) Weg?


----------



## mvitz (5. Jun 2010)

Hm. Das mit dem Spring App Context hatte ich überlesen, also hab ich mir das gerade nochmal in Ruhe alles durchgelesen.

Das mit der FactoryBean Implementierung war ja schon nicht mehr Urpsrungscode. Also würde ich es ein bisschen anders machen. Dazu habe ich noch eine zweite Idee. Es hängt jedoch auch damit zusammen, ob deine Implementierungen von FooIF Dependencies injeziert bekommen sollen. Ist dies der Fall musst du meiner Meinung nach über den App Context gehen.

Nun die beiden Ideen:
1) Wie du oben schonmal oben irgendwie stehen hast, würde ich für das Problem eben für jede Implementierung von FooIF eine Factory schreiben.

```
public interface FooIFFactory {
  FooIF getNewInstance();
}
```

Überall wo du dann eine Instanz von FooIF erzeugen möchtest, kannst du dir die FooIFFactory injezieren lassen.

2) Wenn du nicht für jede Implementierung von FooIF eine Factory schreiben möchtest, könntest du noch eine generische Factory schreiben, die durch ein String Property gesteuert wird. Hier gäbe es dann die Möglichkeit, diese Factory für jede Implementierung zu erweitern oder aber per Reflection deine Instanz zusammen zu bauen.


```
public class FooIFFactry {
@Autowired
@Qualifier("fooClassName")
private String fooClassName;

...

public FooIF getNewInstance() {
  Class<?> clz = Class.getClassForName(fooClassName);
  return clz.newInstance();
}
```

Die Methoden sind jetzt ausm Kopf, müssen also nicht stimmen.

P.S.: Da fällt mir noch was drittes ein:
3) 2., aber über eine tatsächliche Instanz.

```
public class FooIFFactry {
@Autowired
private FooIF fooImpl;

...

public FooIF getNewInstance() {
  return fooImpl.getClass().newInstance()
}
```


----------



## Noctarius (5. Jun 2010)

Ich versteh den Sinn immer noch nicht. Mach doch einfach eine Factory welcher du mit newInstance(Class<? extends WhatEver> clazz) die zu instanzierende Klasse übergibst. Ich seh keinen Sinn darin das alles 3 und 4x zu abstrahieren.


----------



## Gast2 (5. Jun 2010)

Noctarius hat gesagt.:


> Ich versteh den Sinn immer noch nicht. Mach doch einfach eine Factory welcher du mit newInstance(Class<? extends WhatEver> clazz) die zu instanzierende Klasse übergibst. Ich seh keinen Sinn darin das alles 3 und 4x zu abstrahieren.



Ja hab ich mir auch überlegt... Ist ja dann so ähnlich wie die 1. Idee von oben nur eine normale Factory
Und wie würdest du die Factory dann aurufen?So ungefähr?

```
public class Handler...{

@Autowired
FooIF foo;
@Autowired
Factory factory;

void doSth(){

foo = factory.newInstance(foo.getClass());
//....

}

}
```


----------



## Noctarius (5. Jun 2010)

Ja z.B.


----------



## Gast2 (5. Jun 2010)

Okay werd ich das mal versuchen sieht noch ein bischen gewöhnungsbedürftig aus ...


----------



## mvitz (5. Jun 2010)

Fand ich auch 

Aber ist das nicht evtl. dasselbe wie mein Versuch mit folgendem Code?


```
public class Factory {
  @Autowired
  private FooIF fooImpl;

  public FooIF getNewInstance() {
    return fooImpl.getClass().newInstance();
  }
}
```

Nur dass man sich jetzt in der tatsächlichen Klasse ein Autowired sparen kann?


```
public class Handler...{
 
@Autowired
Factory factory;
 
void doSth(){
 
FooIF foo = factory.getNewInstance();
//....
 
}
 
}
```


----------



## Gast2 (5. Jun 2010)

Ja der Unterschied ist das ich oben eine Factory für alle Klassen hab...
Und bei deiner Variante immer wieder wenn ein neues Objekt hinzukommt die Factory erweitern muss...
Weiß auch nicht was die bessere und saubere Variante ist ^^....


----------



## mvitz (5. Jun 2010)

Soll deine Factory bei jedem Aufruf von newInstance() dieselbe FooIF Implementierung zurückgeben, oder auch hier variabel sein?

Wenn jedesmal dieselbe Implementierung zurückgegeben werden soll, dann bist du auch mit meiner Variante raus. Dann musst du nur die FooIF Implementierung in die Factory injizieren. Im Endeffekt ist der Ansatz identisch, mit deiner Variante könntest du die Factory noch variabler nutzen.


----------



## Gast2 (5. Jun 2010)

mvitz hat gesagt.:


> Soll deine Factory bei jedem Aufruf von newInstance() dieselbe FooIF Implementierung zurückgeben, oder auch hier variabel sein?
> 
> Wenn jedesmal dieselbe Implementierung zurückgegeben werden soll, dann bist du auch mit meiner Variante raus. Dann musst du nur die FooIF Implementierung in die Factory injizieren. Im Endeffekt ist der Ansatz identisch, mit deiner Variante könntest du die Factory noch variabler nutzen.



Ursprünglich ja!!! Aber jetzt wos auch variable geht, passts eigentlich...


----------



## Noctarius (5. Jun 2010)

Ich halte es trotzdem für den falschen Weg, allein schon weil das Injizieren der Factory an dieser Stelle keinen Sinn mehr macht, da kannst du die Methode newInstance als static auch in einer Utility-Class hinterlegen, die Factory per String zu instanzieren macht da quasi keinen Sinn mehr.


----------



## Gast2 (5. Jun 2010)

Noctarius hat gesagt.:


> Ich halte es trotzdem für den falschen Weg, allein schon weil das Injizieren der Factory an dieser Stelle keinen Sinn mehr macht, da kannst du die Methode newInstance als static auch in einer Utility-Class hinterlegen, die Factory per String zu instanzieren macht da quasi keinen Sinn mehr.



Stimmt kann ich auch, jetzt wo dus sagst macht es echt keinen Sinn mehr -.-... Aber ich muss trz einmal ein Objekt injecten damit ich an die Impl komme.


----------



## Noctarius (5. Jun 2010)

Nein musst du nicht:


```
public class InstanzingHelfer {
  public static final <T> T newInstance(Class<T> clazz) {
    ...
    return clazz.newInstance();
    ...
  }
}
```


----------



## Gast2 (5. Jun 2010)

Ja das ist schon klar Oo...
Ich meinte auch wenn die Methode aufgerufen wird


----------



## Noctarius (5. Jun 2010)

Wie wenn die Methode aufgerufen wird? ^^


----------



## Gast2 (6. Jun 2010)

```
public class....
{

@Autowired
FooIF foo;

void doSth(){

foo = InstanzinHelfer.newInstance(foo.getClass());
}

}
```


----------



## Noctarius (6. Jun 2010)

Da brauchst du dann doch kein Autowired mehr? Oo
Autowired ist für automatisches Instanzieren, was in diesem Moment gar nicht mehr passiert.


----------



## Gast2 (6. Jun 2010)

Ja wie ruf ich denn dann die Methode auf... 
Ich will ja nicht FooImpl.class aufrufen!!!!


----------



## Noctarius (6. Jun 2010)

Echt ich versteh dein Problem nicht, welche Methode willst du aufrufen? Junge drückt dich konkret aus, mach von mir aus mehr Codebeispiel als 5 Zeilen.
Mit dem InstanceHelper gibt es keine Methode, die du nicht aufrufen kannst, da diese bereits static ist und so ohne Instanz von InstanceHelper aufgerufen werden kann. Und für FooIF gibt es keine Methode die du nicht aufrufen kannst da du mit dem InstanceHelper eine Instanz dieser erschaffen hast (welche Implementierung des Interfaces auch immer).

Also konkrete Frage oder lass es, langsam komm ich mir blöd vor 100x das selbe zu sagen und das Gefühl zu bekommen du hörst nicht zu oder dir würden die absoluten Grundlagen fehlen (und das letzte glaube ich eigentlich nicht).


----------



## mvitz (6. Jun 2010)

Ich versuche ihm mal zu helfen:

Was er will:
Er will per Spring sagen, welche Implementierung von FooIF verwendet werden soll. Zusätzlich möchte er jedoch mehrere unterschiedliche Instanzen dieser Implementierung verwenden.


Was mir noch nicht ganz klar ist:
Wieso genau, brauchst du mehrere verschiedenen Instanzen, und wieso hilft dir da der Protoype Scope von Spring nicht weiter?


----------



## Noctarius (6. Jun 2010)

Dann macht man mehrere verschiedene Factories, definiert diese als Springbean mit unterschiedlichen IDs und injiziert immer die gewünschte Bean. Alternativ nimmst man die Helper-Class und injiziert in die Klasse, welche die Instanz bekommen soll (entweder per Spring oder was weiß ich woher) den Classname der Implementierung.

[xml]<beans>
		<bean id="factory1" class="com.example.impl.Factory1" />
		<bean id="factory2" class="com.example.impl.Factory2" />
		<bean id="factory3" class="com.example.impl.Factory3" />

		<bean id="foo" class="com.example.Foo">
			<property name="factory" ref="factory1" />
		</bean>

		<bean id="bar" class="com.example.Bar">
			<property name="factory" ref="factory2" />
		</bean>

		<bean id="foobar" class="com.example.FooBar">
			<property name="factory" ref="factory3" />
		</bean>
</beans>[/xml]

oder:

[xml]<beans>
		<bean id="foo" class="com.example.Foo">
			<property name="implementation">com.example.my.Impl1</property>
		</bean>

		<bean id="bar" class="com.example.Bar">
			<property name="implementation">com.example.my.Impl2</property>
		</bean>

		<bean id="foobar" class="com.example.FooBar">
			<property name="implementation">com.example.my.Impl3</property>
		</bean>
</beans>[/xml]

```
public class Foo implements InitializingBean {
    private String implementation;

    public void setImplementation(String implementation) { ... }
    public String getImplementation() { ... }

    public void afterPropertiesSet() throws Exception {
        Some some = InstanceHelper.newInstance(implementation);
    }
}
```

PS: Ich versteh trotzdem nicht den Sinn dahinter. Versuch mal klar zustellen was du machen willst. Ich bin sicher du versuchst das einfach total falsch.


----------



## Gast2 (6. Jun 2010)

Okay ich versuch nochmal zu beschreiben was ich machen will... Ausführlicher!!!

Ich haben Handler der wird nur einmal instanziert und in dieser Handler öffnet einen Eclipse Editor und der brauch immer eine neue Instanz von einer Klasse für die es auch eine Interface gibt...
Also war ich soweit...


```
public interface FooIF{

void doSth();

}
```


```
public class FooImpl{

public void doSth(){
....
}

}
```


```
public class Handler{

public void excecute(){

//hier liegt mein Verständniss Problem
FooIF foo = FooFactory.createFoo(FooImpl.class);
.....
}

}
```

[XML]
<beans>
        <bean id="foo" class="com.example.impl.FooImpl" />
        <!--><bean id="foo" class="com.example.impl.Foo2Impl"/><-->
</beans>
[/XML]

Jop also soweit so gut...
Jetzt muss ich aber jedes mal wenn sich die Impl ändert den Code ändern und NICHT nur die XML Datei!!! Und nun habe ich mich gefragt WOHER ich die Klasse bekomme, damit dass alles im Programmcode(siehe Kommentare) dynamisch bleibt und ich nicht die konkrete Implementierung angeben muss. Und ich nur in der XML meine richtige Klasse konfigurieren muss. Mhm besser?


Und meine Idee war halt mit @Autowired einmal die richtige Implmentierung injecten zu lassen, damit ich diese habe...


----------



## Noctarius (6. Jun 2010)

Steht doch bereits oben in meinem Beispiel. Zweites genauer gesagt.


----------



## Gast2 (6. Jun 2010)

Noctarius hat gesagt.:


> Steht doch bereits oben in meinem Beispiel. Zweites genauer gesagt.



Wollt einfach nochmal genau beschreiben was ich vor hab...

Bin grad noch dabei es zu verstehen... Check net ganz was für dich das Some ist, aber so werd ich es mal versuchen...
Ja implementation und klassenname sind ja identisch...


----------



## Noctarius (6. Jun 2010)

SirWayne hat gesagt.:


> Ja implementation und klassenname sind ja identisch...



Hä? Oo


----------



## Gast2 (6. Jun 2010)

[XML]
    <bean id="foo" class="com.example.FooImpl">
            <property name="implementation">com.example.FooImpl</property>
     </bean>
[/XML]

Oder so eigentlich??? Oder wir reden wir aneinander vorbei Oo -.-


Ah ich glaub jetzt check ich^^...  Die Klasse mit der Property ist soll ne Factory sein??? Oder wie hast du das mit dem Some gemeint????

EDIT: Sowas hier oder?

```
public class FooFactory implements FactoryBean<FooIF>{

	private String implementation;
	
	@Override
	public FooIF getObject() throws Exception {
		return InstanzHelper.newInstance(implementation);
	}

	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}

}
```


----------



## Noctarius (7. Jun 2010)

Mach mal einen richtigen Beispielcode was du willst. Mal sagst du, du willst eine Factory, mal meinst du, du willst eine Instanz der Klasse die du schon hast. Mach ein vollständig (theoretisch) kompilierbares Stück Code, ohne das ganze Gepunkte in Methoden.

Nach wie vor ist mir absolut unklar was du willst.

Versuch den Gedanken mal umzudrehen. Hast du eine Möglichkeit in Sourcecode zu erfahren welche Klasse du brauchst? Bestimmtes Value in einem Datenwert oder sowas? Dann könnte man das in der Factory hart verdrahten.

Normalerweise sollte ein simples Scope=Prototype reichen, alternativ halt massig verschiedene Factory Implementierungen oder die gewünschten Implementierungen direkt in die Klasse injizieren wo sie später gebraucht wird (mein zweites Beispiel) oder in verschiedene Instanzen der Factory injizieren (denke hierbei immer daran, dass du den Qualifier beim Autowired mit angeben musst um die Instanzen zu unterscheiden) oder oder oder.

Trotzdem bin ich fest der Überzeugung du versuchst da Schmu zu machen.


----------



## Gast2 (7. Jun 2010)

Ja werd ich nachher mal machen.

Vielleicht nochmal eine kurze Erklärung was genau das Ziel ist:
Ich will die Klasse NICHT zur Laufzeit festlegen. Das Ziel ist, dass ich in meiner xml Datei einstellen kann welche Implementierung der Klasse ich will. Es GIBT NUR EINE gleichzeitig entweder oder.
Zum Beispiel für den einen Kunden zählt Foo1Impl für den anderen Kunden Foo2Impl... Dann will ich ja nichts mehr im Code ändern, sondern nur in der xml die richtige Impl konfigurieren. Also das ist das Ziel =)!!!


----------



## Noctarius (7. Jun 2010)

[xml]<beans>
        <bean id="fooFactory" class="com.example.FooFactory">
            <property name="implementation">com.example.my.Impl1</property>
        </bean>
[/xml]


```
public class FooFactory implements FactoryBean, InitializingBean {
	private Class<? extends FooIF> clazz;
	private String implementation;

	@Override
	public Object getObject() throws Exception {
		return clazz.newInstance();
	}

	@Override
	public Class getObjectType() {
		return clazz;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}

	@Override
	@SuppressWarnings("unchecked")
	public void afterPropertiesSet() throws Exception {
		clazz = (Class<? extends FooIF>) Class.forName(implementation);
	}

	public void setImplementation(String implementation) {
		this.implementation = implementation;
	}

	public String getImplementation() {
		return implementation;
	}
}
```

PS: Du solltest dir dafür überlegen, ob du die Konfiguration der Klasse nicht per PropertyPlaceholder in eine Properties-Datei verschieben willst.

PPS: Jetzt hast du mich schon so genervt mit deiner Factory, dass ich total verplant habe: Du brauchst doch gar keine Factory wenn du eh nur eine bestimmte Implementierung instanzieren willst. Diese kannst du doch direkt als Bean instanzieren mit Scope Prototype.


----------



## Gast2 (7. Jun 2010)

Noctarius hat gesagt.:


> [xml]
> PS: Du solltest dir dafür überlegen, ob du die Konfiguration der Klasse nicht per PropertyPlaceholder in eine Properties-Datei verschieben willst.



Okay das werd ich mir mal anschauen!!!



Noctarius hat gesagt.:


> [xml]
> PPS: Jetzt hast du mich schon so genervt mit deiner Factory, dass ich total verplant habe: Du brauchst doch gar keine Factory wenn du eh nur eine bestimmte Implementierung instanzieren willst. Diese kannst du doch direkt als Bean instanzieren mit Scope Prototype.



Ja das hatte ich am Anfang ja auch... Aber da der Handler nur einmal instanziert wird, hab ich ja immer die gleiche Instanz und ich brauch für jeden Editor eine neue !!! Darum die Idee mit der Factory oder wie würdest du immer eine neue Instanz ansonsten erstellen...


----------



## Noctarius (7. Jun 2010)

SirWayne hat gesagt.:


> Ja das hatte ich am Anfang ja auch... Aber da der Handler nur einmal instanziert wird, hab ich ja immer die gleiche Instanz und ich brauch für jeden Editor eine neue !!!



Argh -.- Les dir doch mal genau durch was man schreibt. Ich mach es jetzt unüberlesbar! SCOPE PROTOTYPE!


----------



## Gast2 (7. Jun 2010)

JAAA Oo hatte ich doch versucht und das hat nicht geklaaappt...

Also so siehts jetzt aus. Wie würdest es anders machen? Wie gesagt hatte am Anfang anstatt die FooFactory immer das Bean mit der richtigen Impl mit Scope Prototype, aber da der Handler nur einmal instanziert wird, hatte ich auch immer die gleiche Instanz!!!
Jetzt

```
public class Handler extends AbstractHandler{


@Autowired
FooFactory factory;

private Object execute(){

FooIF foo = factory.getObject();
//neuen Editor erstellen
}

}
```

Vorher

```
public class Handler extends AbstractHandler{


@Autowired
FooIF foo;

private Object execute(){


//neuen Editor mit foo erstellen
}

}
```

[XML]
<beans>
        <bean id="foo" class="com.example.impl.FooImpl" scope="prototype"/>
</beans>
[/XML]


----------



## Noctarius (7. Jun 2010)

Dafür ist das Factorybean auch nicht gedacht. Das FactoryBean injiziert nicht das FactoryBean selber sondern eine fertige Instanz der Klasse die es bilden soll. Jetzt habe ich endlich verstanden was du machen willst.

Dafür kannst du das FactoryBean nicht verwenden. Mach einfach eine Klasse FooFactory (ohne Implementierung von FactoryBean) und mach die Methode getObject gleich von der Rückgabe her richtig. Z.B. wie in folgendem Snippet:


```
public class FooFactory implements InitializingBean {
    private Class<? extends FooIF> clazz;
    private String implementation;
 
    public FooIF newInstance() throws Exception {
        return clazz.newInstance();
    }
 
    @Override
    @SuppressWarnings("unchecked")
    public void afterPropertiesSet() throws Exception {
        clazz = (Class<? extends FooIF>) Class.forName(implementation);
    }
 
    public void setImplementation(String implementation) {
        this.implementation = implementation;
    }
 
    public String getImplementation() {
        return implementation;
    }
}
```

PS: Denk dran, dass Class.forName in OSGI eventuell nicht funktioniert und du die Klasse per BundleClassLoader oder so laden musst (ka wie das genau in Eclipse funktioniert)


----------



## Gast2 (7. Jun 2010)

Okay versuch ich die Sache mal so Oo...


----------



## Noctarius (7. Jun 2010)

Noch mal das FactoryBean injiziert nicht sich selber sondern beim Injizieren wird von Spring getObject aufgerufen und das zurückgegebene Objekt injiziert. Ergo lässt sich die FactoryBean so wie du möchtest nicht verwenden. Du müsstest quasi eine FactoryBean erzeugen welche dann die eigentliche FactoryBean injiziert, was ziemlich sinnfrei wäre.


----------



## Gast2 (7. Jun 2010)

Ja da mit dem getObject war mir klar, das hab ich davor mal getestet!
1. Aber eigentlich kann ich ja auch ein normales Bean nehmen den scope Protoype setzen und jedes mal aus dem app context mit getBean das Bean neu raus holen oder?
2. Versteh ich den Sinn der FacortyBean nicht so ganz hab mir die Sache in der Spring Doku nochmal durchgelesen. Die FacortyBean macht doch nur Sinn wenn das Object das bei getObject zurückgeliefert wird keine Spring Sachen mehr injeziert oder? Weill wenn ich dort eine Instanz z.B. mit new Instanzier werden alle Spring z.B. Autowired nicht injeziert. Oder wie instanzier ich bei einer FactoryBean bei getObject das Objekt richtig?


----------



## Noctarius (7. Jun 2010)

Das FactoryBean macht schon Sinn, es kommt ja drauf an, wie die Instanz welche ich injizieren will erzeugen muss. Z.B. hat Lycia eine eigene statische Factory welche die Instanzen des Parsers erzeugt.

Um dann eine Instanz zu erzeugen benötige ich eine FactoryBean für Spring, hier z.B.:
LyciaSpringFactory.java - lycia - Project Hosting on Google Code


----------



## Gast2 (7. Jun 2010)

Mhm okay er erzeugt eine neue Instanz in getObject, aber wenn in dieser Klasse irgendwelche Autowired sind, werden diese nicht mit injected oder?


----------



## Noctarius (7. Jun 2010)

Doch ich glaube werden sie auch. Habe ich noch nie probiert aber der Logik nach würde ich sagen, dass Spring einfach alle Fields der Klasse abläuft und schaut ob dort auch wieder Annotations anliegen.

Ein einfacher Minitest würde dir sagen ja / nein


----------



## Gast2 (7. Jun 2010)

Ja ich hab sowas mal versucht aber ich dachte ich hab bestimmt was falsch gemacht ...
Ich denk weil ich wahrscheinlich das getObject selber aufgerufen habe.

Hatte sowas hier hat nicht funktinoniert team war immer null und wurde nicht injected...

```
public class FactoryTeamEditorInput implements FactoryBean<TeamEditorInput>{

	@Override
	public TeamEditorInputgetObject() throws Exception {
		return new TeamEditorInput();
	}

	@Override
	public Class<?> getObjectType() {
		return TeamEditorSite.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}

}
```


```
public class TeamEditorInput implements IEditorInput{

	@Autowired
	private TeamObjectModel team;
	

	@Override
	public boolean exists() {
		// TODO Auto-generated method stub
		return false;
	}

...
}
```

Aufurf vielleicht noch


```
package handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.handlers.HandlerUtil;
import org.springframework.beans.factory.annotation.Autowired;

import ui.editor.FactoryTeamEditor;
import ui.editor.TeamEditor;

public class TeamEditorHandler extends AbstractHandler{

	@Autowired
	FactoryTeamEditor editorSite;
	
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {	
		try {
			HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().openEditor(editorSite.getObject(), TeamEditor.ID);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	

}
```


----------



## Noctarius (7. Jun 2010)

Klar wenn du getObject selber aufrufst dann wird das nicht von Spring verwaltet (kann ja auch nicht). Dafür gibt es aber die außerordentlich gute Spring-Doku wo das eigentlich (meiner Meinung nach) fast nicht besser erklärt sein könnte.


----------



## Gast2 (7. Jun 2010)

Noctarius hat gesagt.:


> Klar wenn du getObject selber aufrufst dann wird das nicht von Spring verwaltet (kann ja auch nicht). Dafür gibt es aber die außerordentlich gute Spring-Doku wo das eigentlich (meiner Meinung nach) fast nicht besser erklärt sein könnte.



Jo wie gesagt, dass war mir klar ist ja auch schon paar Wochen her. Aber darum hab ich die FactoryBean auch nicht richtig verstanden oder bzw. kein Anwendungsgebiet gefunden. Ich hab nicht verstanden wann getObject() genau augerufen wird, auf jeden Fall beim Laden der XML aber auch da war das team dann null und hab ich es gelassen Oo...


----------



## Noctarius (7. Jun 2010)

Tja hätte der Herr mal die Doku gelesen ^^


----------



## Gast2 (7. Jun 2010)

Also ich hab dazu nichts in der Doku gefunden^^...
Ich dachte wenn Spring die getObject Methode aufruft wird auch der Rest von der Klasse injected...

Aber noch zu meiner anderen idee wenn ich das Bean einfach aus dem Application Context mit getBean raushole habe ich ja auch immer die richtige Impl und kann diese Klasse instanzieren oder ist das unsauberer wie deine Lösung oben?


----------



## Noctarius (7. Jun 2010)

Wenn Spring die aufruft tut er das bestimmt auch  Wenn du die aufrufst, dann nicht


----------



## Gast2 (7. Jun 2010)

Mhm also ich habe es damals so versucht und da hat es nicht geklappt.

Factory

```
public class FactoryTeamEditorInput implements FactoryBean<TeamEditorInput>{

	@Override
	public TeamEditorInput getObject() throws Exception {
		return new TeamEditorInput();
	}

	@Override
	public Class<?> getObjectType() {
		return TeamEditorInput.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}

}
```
Bean

```
public class TeamEditorSite implements IEditorInput{

	@Autowired
	private TeamObjectModel team;

	public TeamObjectModel getTeam() {
		return team;
	}

	@Override
	public boolean exists() {
		// TODO Auto-generated method stub
		return false;
	}
```


```
public class CreateTeamEditor extends AbstractHandler{

	@Autowired
	private TeamEditorInput editorInput;
	
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {	
		try {
			System.out.println(editorInput.getTeam());
			HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().openEditor(editorInput, TeamEditor.ID);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
```
[XML]
	<bean id="createTeamEditor" class="handler.CreateTeamEditor"/>

	<bean id="editorInput" class="ui.editor.FactoryTeamEditorInput" scope="prototype"/>

	<bean id="teamObject"  class="objectModel.TeamObjectModel" scope="prototype"/>
[/XML]


----------



## Noctarius (7. Jun 2010)

Eine Factory setzt man nicht auf Scope Prototype


----------



## Gast2 (8. Jun 2010)

Noctarius hat gesagt.:


> Eine Factory setzt man nicht auf Scope Prototype



okay =)... Funktioniert bei mir trotzdem nicht...


----------



## Noctarius (8. Jun 2010)

Hmm ka *schulter zuck* müsst ich auch selber ausprobieren.


----------



## Gast2 (8. Jun 2010)

Noctarius hat gesagt.:


> Hmm ka *schulter zuck* müsst ich auch selber ausprobieren.



hehe okay auf jeden Fall versuch ich das andere mal!!!


----------

