Spring使用@Autowired不能注入BlockingQueue的问题

 

今天遇到一个问题,使用spring4配置BlockingQueue,在Java代码里面使用@Autowired注释方式注入该BlockingQueue,一直报错。

我的代码如下:

    @Autowired
    private BlockingQueue<CoreTask> alarmInnerQueue;

 

我的XML如下:

<bean id="alarmInnerQueue" class="org.kanpiaoxue.test.concurrent.UniqueLinkedBlockingQueue"/>

 说明一下,UniqueLinkedBlockingQueue 这个类是BlockingQueue的一个实现,我自己写的。

报错如下:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.concurrent.BlockingQueue com.baidu.rigel.dmap.sf.service.impl.AlarmFailureServiceImplTest.alarmInnerQueue; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.util.HashMap$Values' to required type 'java.util.concurrent.BlockingQueue'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.util.HashMap$Values] to required type [java.util.concurrent.BlockingQueue]: no matching editors or conversion strategy found
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
	... 26 more
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.util.HashMap$Values' to required type 'java.util.concurrent.BlockingQueue'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.util.HashMap$Values] to required type [java.util.concurrent.BlockingQueue]: no matching editors or conversion strategy found
	at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:74)
	at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:40)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1014)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
	... 28 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.util.HashMap$Values] to required type [java.util.concurrent.BlockingQueue]: no matching editors or conversion strategy found
	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:287)
	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:107)
	at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
	... 32 more

 最后在spring的网站发现这是一个Bug,到现在还没有修复。而是采用了配置

javax.annotation.Resource的方式来绕过这个BUG。

正确的代码如下:

    @Resource(name="alarmInnerQueue")
    private BlockingQueue<CoreTask> alarmInnerQueue;

 

 

网站地址:https://jira.spring.io/browse/SPR-7798

http://forum.spring.io/forum/spring-projects/container/64548-problem-injecting-blockingqueue-by-applicationcontext-xml

内容:

Details

  • Type: Bug Bug
  • Status: RESOLVED
  • Priority: Minor Minor
  • Resolution: Duplicate
  • Affects Version/s: 3.0.5
  • Fix Version/s: None
  • Component/s: Core:AOP
  • Labels:
    None

Description

Cannot @Autowire to inject an instance of java.util.concurrent.BlockingQueue. The above forum has a post from 2009. I was able to reproduce this problem and have attached a minimal example. This works with XML based bean configuration but not with the annotation @Autowired.

AppComponent.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example;
 
import java.util.concurrent.BlockingQueue;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
 
@Component
public class AppComponent {
 
     @Autowired
     public BlockingQueue queue;
 
     public static void main(String[] args) {
 
         new ClassPathXmlApplicationContext("com/example/context.xml").getBean(AppComponent.class);
     }
}

Config.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example;
 
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class Config {
 
     @Bean
     public BlockingQueue blockingQueue() {
         return new LinkedBlockingQueue();
     }
}

context.xml:

1
2
3
4
5
6
7
8
9
10
11
12

The runtime error is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appComponent': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.concurrent.BlockingQueue com.example.AppComponent.queue; nested exception is org.springframework.beans.FatalBeanException: No element type declared for collection [java.util.concurrent.BlockingQueue]
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
     at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
     at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
     at com.example.AppComponent.main(AppComponent.java:17)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.concurrent.BlockingQueue com.example.AppComponent.queue; nested exception is org.springframework.beans.FatalBeanException: No element type declared for collection [java.util.concurrent.BlockingQueue]
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
     at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
     ... 13 more
Caused by: org.springframework.beans.FatalBeanException: No element type declared for collection [java.util.concurrent.BlockingQueue]
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:740)
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
     ... 15 more

Attachments

Issue Links

is superseded by

Activity

 
Michael F added a comment -  05/Jul/11 7:13 AM

(I posted the same response in the forum thread linked above.)

If you want auto-wire the Queue try to use JSR-250's @Resource annotation and a reasonable qualifier. Spring supports these annotations and should correctly inject the queue.)

1
2
3
4
5
@Component
public class B {
   @Resource(name="myBlockingQueue")
   private BlockingQueue<Integer> blockingQueue;
}

@Autowired and @Resource behave differently.

Background info can be found in the documentation: Fine-tuning annotation-based autowiring with qualifiers

Chris Beams added a comment -  07/Jul/11 6:51 PM

Please see SPR-8519, which aims to address this and a number of other similar issues related to collection autowiring.

Marty Kube added a comment -  10/Jul/11 6:16 PM

Great, thanks. @Resource solved the issue.

猜你喜欢

转载自kanpiaoxue.iteye.com/blog/2164479