spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
55.81k stars 37.84k forks source link

`findAutowireCandidates()` will either return candidates that are not selfReferenced or self referenced Collection/Map beans. Not both. #33136

Closed ankitkpd closed 2 weeks ago

ankitkpd commented 4 weeks ago
          Looks like after the fix `findAutowireCandidates()` will either return candidates that are not selfReferenced or candidates that are Collection/Map beans and are self referenced. 

But it won't return both i.e. non self referenced candidates that are being added with

for (String candidate : candidateNames) {
    if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
    }
}

AND candidates that are Collection/Map beans & are self referenced being added with the fix i.e.

for (String candidate : candidateNames) {
    if (isSelfReference(beanName, candidate) &&
            (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
            isAutowireCandidate(candidate, fallbackDescriptor)) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
    }
}

Because if condition if (result.isEmpty()) would prevent it to do so.

Is there a way to get autowired candidates of both types?

Originally posted by @ankitkpd in https://github.com/spring-projects/spring-framework/issues/13096#issuecomment-2073032069

snicoll commented 4 weeks ago

@ankitkpd rather than an analysis of our own code, please explain what you're trying to do. To speed up support, you can share a sample we can actually run to reproduce that behavior ourselves (no code in text please).

spring-projects-issues commented 3 weeks ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues commented 2 weeks ago

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

ankitkpd commented 2 weeks ago

@snicoll within my system I have a base class for all spring configurations that holds a few autowired list for e.g.

@Configuration
public class BaseSharedSpringConfiguration {

  @Autowired(required = false)
  public List<Foo> fooList;

  @Bean
  public Foo sharedFoo() {
    return new BaseSharedFoo();
  }

}

Then there two separate codebases & spring boot apps with their own spring configurations. One extends BaseSharedSpringConfiguration & Other do not for e.g.

@Configuration
public class OneSpringConfiguration extends BaseSharedSpringConfiguration {

  @Bean
  public Foo oneFoo() {
    return new OneTypeOfFoo();
  }

}
@Configuration
public class OtherSpringConfiguration {

  @Autowired
  BaseSharedSpringConfiguration baseSharedConfig;

  @Bean
  public Foo otherFoo() {
    return new OtherTypeOfFoo();
  }

}

With these spring configurations setup sharedFoo & oneFoo are not getting added to the autowired fooList.

With little bit of debugging into DefaultListableBeanFactory.findAutowireCandidates method it was realized that it's because sharedFoo & oneFoo are considered as self referenced beans & otherFoo is not.

Thanks for your support.

snicoll commented 1 week ago

With these spring configurations setup sharedFoo & oneFoo are not getting added to the autowired fooList.

You need to make the injection of the list lazy (or not using field injection) as you're trying in the same arrangement to contribute one instance and inject the list. If you have further questions, please follow-up on StackOverflow.