使用@component定义bean并从XML读取List时出错

时间:2018-04-30 21:47:41

标签: java spring javabeans spring-annotations

我必须说我是春天的新手,所以很可能这对你来说很容易阅读。

我的例子非常简单。我有MainBusinessClient类,以便getClients Business我创建了包含{ClientInterface的接口<List>Client 1}},Autowiredbeans.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();

    }

}

主要

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 :(得分:1)

虽然您可以应用许多Java和Spring约定来改进代码(私有字段而不是公共字段,在bean方法中初始化新的ApplicationContext等),但我将关注主要问题。

您可以简单地删除自动装配列表上的@Qualifier注释 - Spring可以根据您的类型根据您的配置识别所需的bean。

此更改后代码可以运行。