0
votes

Spring Boot - Service de câblage automatique avec constructeur String

Comment puis-je @autowire bean class TransactionManagerImpl qui a 1 constructeur d'argument (String) sans utiliser new dans l'application spring-boot? Même après avoir parcouru de nombreux articles, je n'ai pas pu obtenir d'indice sur autowire sans utiliser new

Je dois autowire TransactionManager dans trois classes différentes et les paramètres sont différents dans les trois classes.

Cela ressemble à un scénario très basique.

@Service
public class TransactionManagerImpl implements TransactionManager {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    String txnLogFile;

    @ConstructorProperties({"txnLogFile"})
    public TransactionManagerImpl(String txnLogFile) {
        this.txnLogFile= txnLogFile; 
    }

}


8 commentaires

D'où vient txnLogFile? Cela créera de toute façon une instance singleton. Si vous avez 3 implémentations différentes, vous devrez utiliser @Qualifier pour les distinguer. Vous pouvez toujours utiliser ApplicationContext pour obtenir ce dont vous avez besoin et y fournir des arguments de contrctor. Vous pouvez également utiliser @Bean avec un qualificatif comme dans answer.


txnLogFile provient du fichier de propriétés. Et il existe trois fichiers journaux différents. En fonction des trois transactions diff, j'injecterai taxLogFile à transactionManager qui écrira dans txnLogFile


Vous pouvez également utiliser @Value directement sur l'argument du constructeur.


@Antoniossss qui ne lira qu'une seule valeur, donc je dois avoir trois impl de TransactionManager


Oui, c'est pourquoi vous devez soit distinguer ces valeurs par implémentation, soit obtenir des beans du contexte d'application en fournissant la chaîne requise comme arg. Dans les deux cas, un qualificatif est nécessaire.


@Antoniossss et si j'enregistre TransactionManager et obtient le bean en utilisant applicationContext en passant le paramètre comme ci-dessous? @Value ("$ {app.type-a.txn-log-file}") private String txnLogFile; Contexte ApplicationContext privé @Autowired; TransactionManager transactionManager = context.getBean (TransactionManager.class, txnLogFile);


C'est ce que je dis que tu peux faire depuis le début (mon premier commentaire)


continuons cette discussion dans le chat .


3 Réponses :


2
votes

Y a-t-il une exigence spécifique pour laquelle vous souhaitez utiliser l'annotation @Service? sinon, vous pouvez utiliser @Bean pour créer un bean pour TransactionManagerImpl comme ci-dessous.

@Configuration
public class Config {

@Value("${txnLogFile}")
private String txnLogFile;

@Bean
public TransactionManager transactionManager() {
    return new TransactionManagerImpl(txnLogFile);
 }

}

et supprimer l'annotation @Service de TransactionManagerImpl.


0 commentaires

0
votes

En mettant de côté les autres complications, cela peut être fait comme ceci

public TransactionManagerImpl(@Value("${txnLogFile}") String txnLogFile) {
    this.txnLogFile= txnLogFile; 
}


0 commentaires

0
votes

Enfin, je l'ai fait comme ci-dessous, maintenant sûr que c'est la meilleure façon de faire. Je ne voulais pas avoir trois implémentations uniquement à cause d'une variable.

application.yaml

public class TransactionManagerImpl implements TransactionManager {

    @Autowired
    private ApplicationContext applicationContext;

    private String txnLogFile;

    public TransactionManagerImpl(String txnLogFile) {
        this.txnLogFile = txnLogFile;
    }

    private CsvService csvService;

    @PostConstruct
    public void init() {
        csvService = applicationContext.getBean(CsvService.class, txnLogFile);
    }

    public ZonedDateTime create() throws IOException, ParseException {
        try {
            csvService.createTxnInfoFile();
            return csvService.getLastSuccessfulTxnTimestamp();
        } catch (IOException e) {
            throw new IOException("Exception occured in getTxnStartDate()", e);
        }
    }

}

MainApplication.java

@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public interface TransactionManager {

    public ZonedDateTime create() throws IOException, ParseException;

}

TypeOneRoute.java

@Configuration
public class TypeTwoRoute extends RouteBuilder {

    @Value("${app.type-b.txn-log-file}")
    private String txnLogFile;

    @Autowired
    private ApplicationContext applicationContext;

    private TransactionManager transactionManager;

    @Override
    public void configure() throws Exception {
        transactionManager = applicationContext.getBean(TransactionManager.class, txnLogFile);
        transactionManager.create();

    }
}

TypeTwoRoute.java

@Configuration
public class TypeOneRoute extends RouteBuilder {

    @Value("${app.type-a.txn-log-file}")
    private String txnLogFile;

    @Autowired
    private ApplicationContext applicationContext;

    private TransactionManager transactionManager;

    @Override
    public void configure() throws Exception {
        transactionManager = applicationContext.getBean(TransactionManager.class, txnLogFile);
        transactionManager.someOperation();

    }
}

TransactionManager.java

@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(MainApplication.class).web(WebApplicationType.NONE).run(args);
    }

    @Bean
    public TransactionManager transactionManager(@Value("${app.default.txn-log-file}") String txnLogFile) {
        return new TransactionManagerImpl(txnLogFile);
    }

    @Bean
    public CsvService csvService(String txnLogFile) {
        return new CsvServiceImpl(txnLogFile);
    }
}

TransactionManagerImpl.java

app:
   type-a:
      txn-log-file: data/type-a-txn-info.csv
   type-b:
      txn-log-file: data/type-b-txn-info.csv
   default: 
      txn-log-file: data/default/txn-info.csv

Initialement, TransactionManager Bean sera enregistré avec app.default.txn-info.csv et quand je l'obtiendrai réellement depuis ApplicationContext Je remplace la valeur par le paramètre passé pour obtenir le bean de ApplicationContext


0 commentaires