Ошибка при определении bean-компонента с @component и чтении List из XML - PullRequest
0 голосов
/ 01 мая 2018

Я должен сказать, что я новичок в Spring, так что, скорее всего, вам будет легко прочитать это.

Мой пример очень прост. У меня есть классы Main, Business и Client, чтобы getClients из Business я создал интерфейс ClientInterface, который содержит <List>Client, Autowired для списка в beans.xml .

То, что я пытаюсь сделать, это напечатать клиентов, которые есть у Бизнеса, но это выдает мне следующую ошибку:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clients': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.List com.springcourse.practice.Client.listClients; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.springcourse.practice.Main.main(Main.java:9)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.List com.springcourse.practice.Client.listClients; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    ... 13 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:814)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
    ... 15 more

Вот содержание кода

beans.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-3.2.xsd">

    <context:component-scan base-package="com.springcourse.practice"></context:component-scan>

    <bean id="arrayClients" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <ref bean="firstClient"/>
                <ref bean="secondClient"/>
                <ref bean="thirdClient"/>
            </list>
        </constructor-arg>
    </bean>

    <bean id="firstClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 1"/>
        <property name="address" value="Somewhere 1"/>
    </bean>

    <bean id="secondClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 2"/>
        <property name="address" value="Somewhere 2"/>
    </bean>

    <bean id="thirdClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 3"/>
        <property name="address" value="Somewhere 3"/>
    </bean>

</beans>

ClientInterface

package com.springcourse.practice;

import java.util.List;

public interface ClientInterface {

    public List<Client> getClients();

}

Клиент

package com.springcourse.practice;

import java.util.List;

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

@Component("clients")
public class Client implements ClientInterface {

    public String name;
    public String address;

    @Autowired
    @Qualifier("arrayClients")
    public List<Client> listClients;

    public List<Client> getClients(){
        return listClients;
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

}

Бизнес

package com.springcourse.practice;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component("business")
public class Business {

    public String name = "Programmer City";

    public String getName() {
        return name;
    }

    public String getClients() {

        @SuppressWarnings("resource")
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/beans.xml");
        Client clients  = (Client) context.getBean("clients");

        StringBuilder sb = new StringBuilder("The business name is: " + this.getName() + "\n");
        sb.append("The clients the business " + this.getName() + " has are: \n");       
        for(Client client: clients.getClients()) {
            sb.append("Client: " + client.name + " located in " + client.address + "\n");
        }

        return sb.toString();

    }

}

Main

package com.springcourse.practice;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/beans.xml");
        Business business  = (Business) context.getBean("business");
        System.out.println(business.getClients());
        context.close();


    }

}

Может кто-нибудь сказать мне, что я делаю не так? Вот ссылка на проект, если кто-то хочет его протестировать: https://www.dropbox.com/s/isqahsxmxw8uxc1/Cap2_PracticeBusinessLocations_2.zip?dl=0

Очень сложно понять ошибки. Большое спасибо всем!

Редактировать beans.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-3.2.xsd">

    <context:component-scan base-package="com.springcourse.practice"></context:component-scan>

    <bean id="arrayClients" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <ref bean="firstClient"/>
                <ref bean="secondClient"/>
                <ref bean="thirdClient"/>
            </list>
        </constructor-arg>
    </bean>

    <bean id="firstClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 1"/>
        <property name="address" value="Somewhere 1"/>
    </bean>

    <bean id="secondClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 2"/>
        <property name="address" value="Somewhere 2"/>
    </bean>

    <bean id="thirdClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 3"/>
        <property name="address" value="Somewhere 3"/>
    </bean>

    <bean id="arrayClientsTheSecond" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <ref bean="TheSecondfirstClient"/>
                <ref bean="TheSecondsecondClient"/>
                <ref bean="TheSecondthirdClient"/>
            </list>
        </constructor-arg>
    </bean>

    <bean id="TheSecondfirstClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 4"/>
        <property name="address" value="Somewhere 4"/>
    </bean>

    <bean id="TheSecondsecondClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 5"/>
        <property name="address" value="Somewhere 5"/>
    </bean>

    <bean id="TheSecondthirdClient" class="com.springcourse.practice.Client">
        <property name="name" value="Client Name 6"/>
        <property name="address" value="Somewhere 6"/>
    </bean>

</beans>

Когда я выполняю ответ:

The business name is: Programmer City
The clients the business Programmer City has are: 
Client: Client Name 1 located in Somewhere 1
Client: Client Name 2 located in Somewhere 2
Client: Client Name 3 located in Somewhere 3
Client: Client Name 4 located in Somewhere 4
Client: Client Name 5 located in Somewhere 5
Client: Client Name 6 located in Somewhere 6

Но опять же, два списка названы по-разному, и элементы списка тоже.

1 Ответ

0 голосов
/ 01 мая 2018

Несмотря на то, что существует множество соглашений Java и Spring, которые можно применять для улучшения кода (частные поля вместо открытых, инициализация нового ApplicationContext внутри метода bean-компонента и т. Д.), Я сосредоточусь на основной проблеме.

Вы можете просто удалить аннотацию @Qualifier в списке автоматических соединений - Spring может определить требуемые bean-компоненты на основе вашей конфигурации по их типу.

Код работает после этого изменения.

...