使用 @component 定义 bean 并从 XML 读取列表时出错
Error while defining a bean with @component and reading List from XML
我必须说我是 Spring 的新手,所以很可能这对阅读本文的您来说很容易。
我的例子很简单。我有 类 Main
、Business
和 Client
,为了从 Business
getClients
我创建了接口 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.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>
客户端界面
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();
}
}
有人可以告诉我我做错了什么吗?如果有人想测试它,这里有一个 link 的项目: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
但同样,这两个列表的名称不同,列表元素也不同。
虽然您可以应用许多 Java 和 Spring 约定来改进您的代码(私有字段而不是 public,在 bean 方法中初始化一个新的 ApplicationContext,等等.), 我将专注于主要问题。
您可以简单地删除自动装配列表上的@Qualifier 注释 - Spring 可以根据您的配置按类型识别所需的 bean。
此更改后代码有效。
我必须说我是 Spring 的新手,所以很可能这对阅读本文的您来说很容易。
我的例子很简单。我有 类 Main
、Business
和 Client
,为了从 Business
getClients
我创建了接口 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.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>
客户端界面
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();
}
}
有人可以告诉我我做错了什么吗?如果有人想测试它,这里有一个 link 的项目: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
但同样,这两个列表的名称不同,列表元素也不同。
虽然您可以应用许多 Java 和 Spring 约定来改进您的代码(私有字段而不是 public,在 bean 方法中初始化一个新的 ApplicationContext,等等.), 我将专注于主要问题。
您可以简单地删除自动装配列表上的@Qualifier 注释 - Spring 可以根据您的配置按类型识别所需的 bean。
此更改后代码有效。