Le printemps ne parvient pas à autoriser automatiquement mon objet? Est-il possible d'autowire un objet dans une classe abstraite. Supposons que tous les schémas sont fournis dans application-context.xml
Question: Quelle annotation doit figurer sur la base et sur les classes d'extension (le cas échéant) @Service @Component?
Exemple
abstract class SuperMan {
@Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Classe d'extension
public class SuperGirl extends SuperMan {
@Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
Normalement, Spring devrait effectuer le câblage automatique, tant que votre classe abstraite se trouve dans le package de base fourni pour l'analyse des composants.
Voir this et this pour une référence ultérieure.
@Service
et @Component
sont deux stéréotypes qui créent des beans du type annoté dans le conteneur Spring. En tant que document Spring Docs,
Cette annotation sert de spécialisation de @Component, permettant à les classes d'implémentation à détecter automatiquement via l'analyse de chemin d'accès aux classes.
J'ai ce genre de configuration de printemps de travail
une classe abstraite avec un champ auto-câblé
public abstract class AbstractJobRoute extends RouteBuilder {
@Autowired
private GlobalSettingsService settingsService;
et plusieurs enfants définis avec l'annotation @Component
.
Dans mon cas, dans une application Spring4, je devais utiliser un motif abstrait d'usine classique (pour lequel j'ai pris l'idée de - http://Java-design-patterns.com/patterns/abstract-factory/ ) pour créer des instances à chaque fois qu’une opération devait être effectuée. Mon code devait donc être conçu de la manière suivante:
public abstract class EO {
@Autowired
protected SmsNotificationService smsNotificationService;
@Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
@Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
@Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initialement pour injecter les dépendances dans la classe abstraite, j’ai essayé toutes les annotations de stéréotypes comme @Component, @Service, etc. mais même si le fichier de contexte Spring avait ComponentScanning pour l’ensemble du paquet, Ayant nul pour ses propriétés car Spring était incapable de reconnaître et d'injecter ses dépendances. Après de nombreux essais et erreurs, j'ai utilisé cette annotation **@Configurable(dependencyCheck = true)**
et enfin Spring a pu injecter les dépendances et j'ai pu utiliser les propriétés de la sous-classe sans les encombrer trop de propriétés.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
J'ai aussi essayé ces autres références pour trouver une solution:
S'il vous plaît essayez d'utiliser **@Configurable(dependencyCheck = true)**
et mettre à jour ce post, je pourrais essayer de vous aider si vous rencontrez des problèmes.
Et si vous avez besoin d’une opération de base de données dans SuperGirl
, vous l’injecterez à nouveau dans SuperGirl
.
Je pense que l'idée principale est d'utiliser la même référence d'objet dans différentes classes. Alors qu'en est-il de ceci:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
@Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
@Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
@Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
A mon avis, injecter une fois courir partout :)