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?
Shalom@ManagedProperty
i pozwalać na dynamiczne zmiany JMXem ;)