使用Spring IoC时,我遇到了从应用程序上下文中获取bean的问题。
我的电话簿应用程序有‘Security Definer’
界面,此界面有3个实现。所有实现都是Spring @Components。我还有一个ContactProvider
,它存储了用户使用的实现。当用户尝试更改实现时,应用程序将抛出NoSuchBeanDefinitionException。为了找出用户想要根据其输入使用哪个实现,我创建了实用程序枚举,其中包含为所有实现提供Preferences
个对象的所有实现。这个类有Class
方法,它根据给定的字符串(用户输入)返回实现类型。
设置新联系人提供者的方法:
fromString()
ContactProviders枚举,我从中获取了一类实现:
private void handleSetProviderCommand(String param) {
ContactProviders providerType = ContactProviders.fromString(param);
Class<? extends ContactProvider> providerClass = providerType.getProviderClass();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
ContactProvider contactProvider = context.getBean(providerClass); // I get NoSuchBeanDefinitionException here
phoneBook.setContactProvider(contactProvider);
Preferences preferences = Preferences.userNodeForPackage(PhoneBook.class);
preferences.put(PreferenceKeys.CONTACT_PROVIDER.getKey(), param);
}
其中一个实现(所有这些实现都使用@Component注释):
public enum ContactProviders {
FILE(FileContactProvider.SHORT_NAME, FileContactProvider.class),
ELASTIC(ElasticContactProvider.SHORT_NAME, ElasticContactProvider.class),
NO_SQL(NoSqlContactProvider.SHORT_NAME, NoSqlContactProvider.class);
private final Class<? extends ContactProvider> providerClass;
private final String shortName;
ContactProviders(String shortName, Class<? extends ContactProvider> providerClass) {
this.shortName = shortName;
this.providerClass = providerClass;
}
public static ContactProviders fromString(String param) {
Optional<ContactProviders> providerType = Arrays.stream(ContactProviders.values())
.filter(cp -> cp.getShortName().equals(param)).findFirst();
if (providerType.isPresent()) {
return providerType.get();
} else {
throw new IllegalArgumentException("Contact provider not recognized: " + param);
}
}
}
我的@Configuration类中还定义了一个bean,用于根据系统中已设置的首选项提供联系提供程序。它接受首选项字符串并创建实现类的实例以返回:
public class FileContactProvider implements ContactProvider {
public static final String SHORT_NAME = "file";
private static final String SEPARATOR = "|";
private List<Contact> contacts;
private Path file;
private Logger logger = LoggerFactory.getLogger(FileContactProvider.class);
public FileContactProvider() {
file = openFile();
contacts = loadContacts();
}
private Path openFile() {
Preferences preferences = Preferences.userNodeForPackage(FileContactProvider.class);
Path file = Paths.get(
preferences.get(
PreferenceKeys.FILE_FILE_NAME.getKey(),
PreferenceKeys.FILE_FILE_NAME.getDefaultValue()
)
);
if (Files.exists(file)) {
try {
if (Files.isReadable(file) && Files.isWritable(file)) {
return file;
} else {
throw new IOException("The file is not readable or writable.");
}
} catch (IOException e) {
logger.error("Error while opening the file: " + e.getMessage());
}
} else {
try {
Files.createFile(file);
} catch (IOException e) {
logger.error("Error while creating a file: " + e.getMessage());
}
}
return file;
}
private void saveFile() {
List<String> contactStrings = new ArrayList<>();
contacts.stream()
.sorted()
.forEach(contact -> contactStrings.add(contact.getName() + SEPARATOR + contact.getNumber()));
try {
Files.write(file, contactStrings);
} catch (IOException e) {
logger.error("Error while saving to the file: " + e.getMessage());
}
}
private List<Contact> loadContacts() {
List<Contact> loaded = new ArrayList<>();
try {
Files.readAllLines(file)
.forEach(line -> {
String[] contactString = StringUtils.split(line, SEPARATOR);
Contact contact = new Contact(contactString[0], contactString[1]);
loaded.add(contact);
});
} catch (IOException e) {
logger.error("Error while reading file content: " + e.getMessage());
}
return loaded;
}
@Override
public Contact save(Contact contact) {
if (contacts.contains(contact)) {
System.out.println("Contact is already in the phone book.");
} else {
contacts.add(contact);
saveFile();
}
return contact;
}
@Override
public List<Contact> find(String name) throws ContactNotFoundException {
List<Contact> found = contacts.stream()
.filter(contact -> StringUtils.indexOf(contact.getName().toLowerCase(), name.toLowerCase()) != -1)
.collect(Collectors.toList());
if (found.isEmpty()) {
throw new ContactNotFoundException(name);
}
return found;
}
@Override
public List<Contact> getAll() {
return contacts;
}
@Override
public void delete(Contact contact) {
contacts.remove(contact);
saveFile();
}
@Override
public void configure() {
System.out.print("Enter file name: ");
String filename = ConsoleUtils.getInput("^[^<>:;,?\"*|/]+$");
Preferences preferences = Preferences.userNodeForPackage(FileContactProvider.class);
preferences.put(PreferenceKeys.FILE_FILE_NAME.getKey(), filename);
file = openFile();
contacts = loadContacts();
}
@Override
public void showConfiguration() {
Preferences preferences = Preferences.userNodeForPackage(FileContactProvider.class);
System.out.println("File name: " +
preferences.get(
PreferenceKeys.FILE_FILE_NAME.getKey(),
PreferenceKeys.FILE_FILE_NAME.getDefaultValue()
)
);
}
}