Kullanım şemasını kullanarak bir Listeyi otomatik olarak kablolamak NoSuchBeanDefinitionException sağlar


90

Spring util ad alanını kullanarak adlandırılmış bir listeyle enjekte etmek istediğim bir fasulyem var, <util:list id="myList">ancak Spring bunun yerine String türünde bir fasulye koleksiyonu arıyor. Bozuk testim:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ListInjectionTest {

    @Autowired @Qualifier("myList") private List<String> stringList;

    @Test public void testNotNull() {
        TestCase.assertNotNull("stringList not null", stringList);
    }
}

Benim bağlamım:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

   <util:list id="myList">
       <value>foo</value>
       <value>bar</value>
   </util:list>

</beans>

Ama anlıyorum

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.lang.String] found for dependency [collection of java.lang.String]: 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=myList)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:726)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:571)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:412)

İşe yaraması beklenen yolun bu olacağını düşündüğüm için beni daha çok şaşırttı.

Yanıtlar:


171

Bu, @ Autowired'ın 3.11.2'de belirtilen davranışının oldukça belirsiz bir kısmından kaynaklanmaktadır . @Autowired :

Belirli bir türdeki tüm fasulyeleri ApplicationContext, ek açıklamayı bu türden bir dizi bekleyen bir alana veya yönteme ekleyerek sağlamak da mümkündür ...

Aynısı daktilo edilmiş koleksiyonlar için de geçerlidir ...

Başka bir deyişle, "myList" niteleyicisine sahip @Autowired @Qualifier("myList") List<String>tüm çekirdek türlerinin listesini bana vermenizi istersiniz java.lang.String.

Çözüm 3.11.3'te belirtilmiştir . Niteleyicilerle ince ayar açıklama tabanlı otomatik kablolama :

Ek açıklamaya dayalı enjeksiyonu isme göre ifade etmeyi düşünüyorsanız @Autowired, teknik olarak @Qualifier değerler aracılığıyla bir fasulye adına atıfta bulunabilecek olsa bile, öncelikle kullanmayın . Bunun yerine, @Resource belirli bir hedef bileşeni benzersiz adıyla tanımlamak için anlamsal olarak tanımlanmış JSR-250 açıklamasını tercih edin , beyan edilen tür eşleştirme işlemi ile ilgisizdir.

Bu anlamsal farkın belirli bir sonucu olarak, kendileri bir koleksiyon veya eşleme türü olarak tanımlanan çekirdekler, @Autowiredtür eşleştirmesi onlar için uygun şekilde uygulanamadığından, yoluyla enjekte edilemez. Bu @Resourcetür çekirdekler için kullanın , özel koleksiyon / harita çekirdeğine benzersiz bir adla atıfta bulunun.

Öyleyse bunu testinizde kullanın ve iyi çalışıyor:

@Resource(name="myList") private List<String> stringList;

9
Siz daha güvendesiniz ve stackoverflow.com da öyle! :)
Rihards

5
Elimde olsa bu on oyu veririm. Sen Da Man'sin, skaffman.
duffymo

3
Birçoğunun bu şekilde kafasının karışmış olması, anlambilimin gerçekten kafa karıştırıcı olduğu anlamına gelir. Bu kadar kafa karıştıran tasarımın arkasındaki sebep neydi merak ediyorum.
supertonsky

3
Vay canına, Bahar'ı programlamadaki en güçlü alanlardan biri olarak görüyorum ve bugüne kadar bu sorunla hiç karşılaşmadım ve bana tonlarca zaman kazandırdın. Teşekkürler!
Avi

2
Bunun yapıcı / yöntem enjeksiyonu ile nasıl çalışacağına dair herhangi bir öneriniz var mı? @Resource parametreyi desteklemiyor mu?
cjbooms

0

Olabilecek başka bir şey de, bir fasulyenin bir özelliğini otomatik olarak kabloluyor olmanızdır. Böyle bir durumda, onu otomatik olarak bağlamanız gerekmez, ancak sadece ayarlayıcı yöntemini oluşturun ve fasulye tanımındaki (xml kullanırken) özellik etiketini kullanın:

<bean id="cleaningUpOldFilesTasklet" class="com.example.mypackage.batch.tasklets.CleanUpOldFilesTasklet">
    <property name="directoriesToClean">
        <list>
            <value>asfs</value>
            <value>fvdvd</value>
            <value>sdfsfcc</value>
            <value>eeerer</value>
            <value>rerrer</value>
        </list>
    </property>
</bean>

Ve sınıf:

public class CleanUpOldFilesTasklet extends TransferingFilesTasklet implements Tasklet{

private long pastMillisForExpiration;
private final String dateFormat = "MM.dd";
Date currentDate = null;

List<String> directoriesToClean;

public void setDirectoriesToClean(List<String> directories){
    List<String> dirs = new ArrayList<>();
    for(String directory : directories){
        dirs.add(getSanitizedDir(directory));
    }
    this.directoriesToClean = dirs;
}

Bak, @Autowiredsınıfta açıklama yok .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.