Как я могу динамически вводить значения в аннотации @Values? (Весенняя Ява)

application.properties содержат данную информацию:

book.name1 = War and Piece
book.author1 = Leo Tolstoy
book.name2 = Crime and Punishment
book.author2 = Dostoevsky 
book.name3 = To Kill a Mockingbird
book.author3 = Harper Lee

И Book.java, который принимает значения из файла.

public class Book {
    String name;
    String author;
    static int bookid = 0;
    
    public Book(){bookid++;}
    
    @Value ("${book.name.concat(bookid)}")
    public void setName(String name)
    {this.name = name;}
    
    @Value ("${book.author.concat(bookid)}")
    public void setAuthor(String name)
    {this.author = author;}
    
    public String getBook()
    {return name + " by " + author;}
}

И, наконец, класс, содержащий массив книг.

public class UniversityLibrary implements Library{
    List<Book> books;
    public UniversityLibrary(ArrayList<Book> books) //books are injected by ConfigClass
    {
        this.books = new ArrayList<>();
        for (Book bok: books)
        {this.books.add(bok);}
    }
}

Результат System.out.println(ubilibrary.getBook(1)) — ${book.name.concat(bookid)} от ${book.author.concat(bookid)} — как и ожидалось, но не удовлетворяет задаче . Создание единой Книги также не помогло бы ситуации.

Нигде не найден правильный синтаксис, чтобы это работало. Я ожидаю, что выражение в Value возьмет значение из bookid и соединит его с ${book.name..}, чтобы получить результат @Value("${book.name1}") и т. д.

application.properties предназначен не для этого. Первым шагом может быть создание CSV-файла с динамически изменяющимися значениями или, что еще лучше, подключение вашего приложения к базе данных.

Valerij Dobler 28.07.2024 11:40

Ваша книга выглядит как классическая Сущность.

Valerij Dobler 28.07.2024 11:41

вы понимаете, что использование идентификатора static приведет к тому, что он будет иметь одинаковое значение во ВСЕХ книгах

J Asgarov 28.07.2024 11:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

это возможно с @ConfigurationProperties

При условии, что у вас есть следующие свойства:

books[0].name = War and Piece
books[0].author = Leo Tolstoy
books[1].name = Crime and Punishment
books[1].author = Dostoevsky 
books[2].name = To Kill a Mockingbird
books[2].author = Harper Lee

вы можете автоматически связать эти свойства с List<Book>:

@ConfigurationProperties
@Component // we either have to define it as component or specifically instruct Spring to scan for this with `@ConfigurationPropertiesScan`
public class BookProperties {

    private List<Book> books;

    // IMPORTANT! without a setter, spring won't bind the values
    public void setBooks(List<Book> books) {
        this.books = books;
    }

    // getter
}

После этого вы можете автоматически подключиться BookProperties куда угодно и получить доступ к списку книг (books).

Для получения дополнительной информации см. соответствующую документацию.


Что касается bookid, вам также следует определить его в свойствах или добавить логику в установщик, НО этого не может быть static, иначе он будет иметь одно и то же значение для ВСЕХ объектов книги (потому что именно так работает static, это свойство уровня класса, а НЕ экземпляр уровень)

bookid — не совсем подходящее имя для этого статического поля. Оно должно было увеличиваться каждый раз при добавлении новой книги (total_books). Спасибо за ваш вклад! попробую с этим поработать

Korol_ER 28.07.2024 18:50

Итак, следуя совету Дж. Аскарова, я получил следующие свойства:

list.books[0].name = War and Piece
list.books[0].author = Leo Tolstoy ...

Оказывается, этот синаксис имеет решающее значение для @ConfigurationProperties. Далее идет класс Book, значения @Value не используются! (Что было для меня новым)

public class Book {
    String name;
    String author;
    public void setName(String name)
    {this.name = name;}

    public void setAuthor(String author)
    {this.author = author;}

    public String getBook()
    {return name + " by " + author;}
}

BookProperties или UniLibrary в моем случае следуют этому шаблону:

@ConfigurationProperties("list") // and this is why list.* in properties is important!!
public class UniversityLibrary implements Library{
    List<Book> books;
    //setter goes here
    //...
}

И последнее, но не менее важное: ConfigClass. За исключением @EnableAspectJAutoProxy (proxyTargetClass=true), убедитесь, что они у вас есть все.

@Configuration
@ComponentScan("koroler.spring.AOP")
@PropertySource("classpath:application.properties")
@ConfigurationPropertiesScan 
@EnableAspectJAutoProxy (proxyTargetClass=true)
public class ConfigClass {
    @Bean
    @Scope ("prototype")
    public Book books()
    {
        return new Book();
    }
    
    @Bean
    public UniversityLibrary uniLibrary()
    {
        return new UniversityLibrary();
    } 
}

В результате ulibrary.getBook(1) возвращает «Преступление и наказание Достоевского», как и ожидалось. Большое спасибо! Я также надеюсь, что этот ответ поможет кому-то, если вы немного застряли в других решениях c:

Другие вопросы по теме