Printemps: Injecter une classe intérieure privée en tant que membre d'une classe externe?
-
23-09-2019 - |
Question
J'ai la structure de classe suivante
public class Outer{
private Mapper a;
....
private class MapperA implements Mapper {
}
private class MapperB implements Mapper {
}
}
Dans mon fichier de configuration Spring je voudrais créer un bean extérieur, et affecter l'une des MapperA ou MapperB comme une propriété. Est-ce possible?
<bean id="outer" class="mypackage.Outer">
<property name="a" ?????='????' />
</bean>
Edit: Un peu plus d'informations, sur la base des commentaires des réponses:
-
Je suis devenu paresseux avec mon exemple ci-dessus. J'ai un setter / getter public pour la variable d'instance Mapper.
-
La raison pour laquelle toutes les classes Mapper sont les classes internes est parce qu'il pourrait potentiellement être beaucoup d'entre eux, et ils ne jamais être utilisé dans cette classe. Je ne veux pas une tonne de classes CRUFT dans mon projet. Peut-être une méthode de fabrication est une meilleure idée.
La solution
Normalement, vous auriez besoin d'un setter pour le Mapper
au sein Outer
, et une instance de la Mapper
nécessaire. Mais comme ceux-ci sont:
- privée
- intérieur
les classes, qui devient un peu plus difficile (que vous avez identifié). Si vous les rendre publics, je suis sûr que vous pouvez CREAE une instance en utilisant etc. Outer$MapperA
Mais cela semble un peu méchant. Donc:
- ont-ils besoin d'être intérieure et privée?
- peut-être extérieur peut prendre une chaîne, et de déterminer à partir de ce que instancier
MapperA
ouMapperB
. à-dire qu'il ya une certaine capacité d'usine ici.
La chose la plus simple à faire est de vraiment déterminer si elles doivent être intérieure / privé. Si oui, alors ils ne devraient vraiment pas être référencée dans la config, qui devrait parler de cours accessibles au public.
Autres conseils
Le printemps peut instancier private
classes internes. Le problème réel avec votre config est qu'ils sont également non-static
, si vous avez besoin d'un <constructor-arg .../>
:
<bean id="outer" class="mypackage.Outer">
<property name = "a">
<bean class = "mypackage.Outer.MapperA">
<constructor-arg ref = "outer" />
</bean>
</property>
</bean>
Pour autant que je sache, il est impossible jusqu'à ce que vous faites MapperA
et MapperB
habituelles classes publiques.
Mais si vous ne voulez les garder comme des cours privés internes, vous pouvez « injecter » manuellement.
Vous devrez créer méthode avec annotation @PostInit
et initialiser votre champ a
il (a = new MapperA ()
par exemple, ou quelque chose de plus complexe). Avec cette approche, vous devez également vérifier que les callbacks d'initialisation sont mis sur la configuration de votre ressort.