Przekazywanie zmiennych typu prostego w Spring Framework.

0

Witam. Od niedawna uczę się Spring Framework i żeby być pewnym, że wszystko dobrze rozumiem, przerabiam stary projekt z Javy SE na taki, który by wykorzystywał różne funkcje Springa. Póki co, w projekcie mam trzy pakiety: app (z klasą uruchamiającą), bean zawierający instancje klas, które chcę uruchomić i appConfig na konfigurację. Teraz tak. W appConfig przechowuję zmienną na użytek beana:

package config;

import beans.CaesarCipher;
import beans.VigenereCipher;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration

public class AppConfig {

    @Bean
    @Qualifier("NumberForCaesarCipher")
    public int getNum()
    {
        return 4;
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer
    getPropertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

Jest ona używana przez klasę CaesarCipher, w której pola i konstruktor korzystający ze zmiennej wyglądają tak:

package beans;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class CaesarCipher implements Cipher {
    
private String alphabet;
    private String shiftedAlphabet;
    @Autowired
    @Qualifier("NumberForCaesarCipher")
    private int key;

    public CaesarCipher(int key) {

        this.key = key;
        alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        shiftedAlphabet = alphabet.substring(key) +
                alphabet.substring(0,key);
        alphabet = alphabet + alphabet.toLowerCase();
        shiftedAlphabet = shiftedAlphabet + shiftedAlphabet.toLowerCase();
    }

Uruchamiane wszystko jest z klasy Application w pakiecie app:

package app;

import beans.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackageClasses = VigenereCipher.class)
public class Application {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Application.class);
        Cipher cc = ctx.getBean(CaesarCipher.class);
        System.out.println(cc.encrypt("message"));
}
}

No i wywala mi błąd:

Apr 13, 2020 12:55:05 PM org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'caesarCipher' defined in file [/home/tomasz/git/repository/springTomkiScrambler/target/classes/beans/CaesarCipher.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'caesarCipher' defined in file [/home/tomasz/git/repository/springTomkiScrambler/target/classes/beans/CaesarCipher.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Który z kolei nie pojawia się, jeśli przeniosę klasę AppConfig do pakietu, w którym znajduje się bean, który ma korzystać ze zmiennej zawartej w tej pierwszej klasie. Jeśli dobrze mniemam, muszę jakoś zaznaczyć, w klasie CaesarCipher żeby korzystała ze zmiennych znajdujących się w innym pakiecie, albo w klasie AppConfig zrobić tak żeby przekazywała swoje zmienne do klas w folderze beans. Tylko jak?

2
    @Bean
    @Qualifier("NumberForCaesarCipher")
    public int getNum()
    {
        return 4;
    }

Aż mnie serce zabolało :D I jak chcesz zmienić tą liczbę to rekompilacja aplikacji? Genialny plan! A teraz weź po ludzk do /src/main/resources wrzuc plik tekstowy application.properties a w nim

caesar.number=4

A następnie w kodzie:

    public CaesarCipher(@Value("${caesar.number}") int key) {

i voila.

1 użytkowników online, w tym zalogowanych: 0, gości: 1