Хотел создать зависимости через application-Context.xml для ArrayList

Хотел создать зависимости через application-Context.xml для ArrayList через setter, но увы ошибка.

В чем может быть проблема?

Визуально не вижу ошибку, но практика говорит о другом.

package ua.vadym;

import org.springframework.beans.factory.annotation.Value;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
    private List<Music> musicList = new ArrayList<>();
    private String name;
    private int volume;

    public MusicPlayer() {

    }

    public void playMusic(List<Music>musicList) {
        for (Music m : musicList) {
            m.getSong();
        }
    }

    public String getName() {
        return name;
    }

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

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public void setMusicList(List<Music> musicList) {
        this.musicList = musicList;
    }
}

Контекст

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="musicPlayer.properties"></context:property-placeholder>
<!--  Bean ClassickMusic-->
    <bean id="classicalMusic"
          class="ua.vadym.ClassicalMusic">
    </bean>
<!--    Bean RockMusic-->
    <bean id="rockMusic"
    class="ua.vadym.RockMusic">
    </bean>
<!--    Bean RapMusic-->
    <bean id="rapMusic"
   class="ua.vadym.RapMusic" ></bean>

<!--    Внедрение зависимости через Сеттер-->
    <bean id="musicPlayer" class="ua.vadym.MusicPlayer">
        <property name="musicList" >
            <list>
                <value type="ua.vadym.RapMusic">classicalMusic</value>
                    <ref bean="classicalMusic"></ref>
                <value type="ua.vadym.RockMusic">rockMusic</value>
                    <ref bean="rockMusic"></ref>
                <value type="ua.vadym.ClassicalMusic">rapMusic</value>
                    <ref bean="rapMusic"></ref>
            </list>
        </property>
    </bean>

</beans>

Main

public class TestSpring {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("application-Context.xml");



        MusicPlayer musicPlayer = context.getBean("musicPlayer", MusicPlayer.class);


        RockMusic rockMusic = context.getBean("rockMusic", RockMusic.class);
        ClassicalMusic classicalMusic = context.getBean("classicalMusic", ClassicalMusic.class);
        RapMusic rapMusic = context.getBean("rapMusic", RapMusic.class);

        List<Music> list = new ArrayList<>();
        list.add(rockMusic);
        list.add(classicalMusic);
        list.add(rapMusic);
        musicPlayer.playMusic(list);
        System.out.println("Done");
        context.close();
    }
}

Ответы (1 шт):

Автор решения: Михаил Ребров

У Вас явная ошибка при определении бина плеера

    <bean id="musicPlayer" class="ua.vadym.MusicPlayer">
        <property name="musicList" >
            <list>
                <value type="ua.vadym.RapMusic">classicalMusic</value>
                    <ref bean="classicalMusic"></ref>
                <value type="ua.vadym.RockMusic">rockMusic</value>
                    <ref bean="rockMusic"></ref>
                <value type="ua.vadym.ClassicalMusic">rapMusic</value>
                    <ref bean="rapMusic"></ref>
            </list>
        </property>
    </bean>

С таким контекстом вы закономерно получаете Exception

сент. 19, 2022 8:53:10 AM org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'musicPlayer' defined in class path resource [application-Context.xml]: Error converting typed String value for bean property 'musicList' with key [0]; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic': no matching editors or conversion strategy found
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'musicPlayer' defined in class path resource [application-Context.xml]: Error converting typed String value for bean property 'musicList' with key [0]; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic': no matching editors or conversion strategy found
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:218)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:428)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:173)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1707)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1452)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
    at ua.vadym.TestSpring.main(TestSpring.java:10)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:76)
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:209)
    ... 16 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262)
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73)
    ... 18 more

В котором вам явно говорят, что Спринг не может привести строку к объекту типа ua.vadym.RapMusic

Вот эта строка

Cannot convert value of type 'java.lang.String' to required type 'ua.vadym.RapMusic':

И вот строка в конфигурации из-за которой она возникла

<value type="ua.vadym.ClassicalMusic">rapMusic</value>

И у остальной музыки будет аналогичная ошибка.

  • во-первых вы неправильно указываете значение объекта
  • во-вторых это действие лишнее, потому что вам вообще не нужно создавать здесь значение.

Вы уже создавали эти объекты ранее

<!--  Bean ClassickMusic-->
<bean id="classicalMusic" class="ua.vadym.ClassicalMusic"></bean>
<!--    Bean RockMusic-->
<bean id="rockMusic" class="ua.vadym.RockMusic"></bean>
<!--    Bean RapMusic-->
<bean id="rapMusic" class="ua.vadym.RapMusic" ></bean>

Все что вам нужно будет сделать это просто сослаться на них в списке

<list>
    <ref bean="classicalMusic"></ref>
    <ref bean="rockMusic"></ref>
    <ref bean="rapMusic"></ref>
</list>

Это все!..

application-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="musicPlayer.properties"></context:property-placeholder>
    <bean id="classicalMusic" class="ua.vadym.ClassicalMusic"></bean>
    <bean id="rockMusic" class="ua.vadym.RockMusic"></bean>
    <bean id="rapMusic" class="ua.vadym.RapMusic" ></bean>
    <bean id="musicPlayer" class="ua.vadym.MusicPlayer">
        <property name="musicList" >
            <list>
                <ref bean="classicalMusic"></ref>
                <ref bean="rockMusic"></ref>
                <ref bean="rapMusic"></ref>
            </list>
        </property>
    </bean>
</beans>

И из main'а вам стоит убрать эти строки

RockMusic rockMusic = context.getBean("rockMusic", RockMusic.class);
ClassicalMusic classicalMusic = context.getBean("classicalMusic", ClassicalMusic.class);
RapMusic rapMusic = context.getBean("rapMusic", RapMusic.class);

List<Music> list = new ArrayList<>();
list.add(rockMusic);
list.add(classicalMusic);
list.add(rapMusic);
musicPlayer.playMusic(list);

вы по сути повторно забираете эти зависимости и передаете их в плеер
У нас все это описано в конфигурации и сам Spring должен за нас это сделать.

К слову о плеере...
Вам стоит заменить реализацию метода playMusic()
(или добавить рядом перегруженный метод)

было

public void playMusic(List<Music>musicList) {
    for (Music m : musicList) {
        m.getSong();
    }
}

Чтобы данный метод работал с внедренным свойством нужен такой

public void playMusic() {
    for (Music m : musicList) {
        m.getSong();
    }
}

И точка входа получится такой:

package ua.vadym;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("application-Context.xml");
        MusicPlayer musicPlayer = context.getBean("musicPlayer", MusicPlayer.class);
        musicPlayer.playMusic();
        System.out.println("Done");
        context.close();
    }
}

тестируем

введите сюда описание изображения

все работает отлично

→ Ссылка