26

How does Spring @Autowire beans: byName or byType? If one is not possible, is a second trial done using another mode?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142

6 Answers6

40

If annotated with @Autowired it will inject the bean with the matching type (An exception will be thrown if there are more than one of a type). To specify a name use the @Qualifier annotation.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Wilhelm Kleu
  • 10,821
  • 4
  • 36
  • 48
  • 2
    Something to add: In Spring 5( I didn't check other versions), when there are more than one of a matching type, spring framework will try to use field name as bean name to determine a proper candidate. This strategy can be found in `DefaultListBeanFacotory#determineAutowireCandidate(Map candidates, DependencyDescriptor descriptor)` – yuqizhang Sep 10 '19 at 03:04
3

Springs @Autowire wires by type. For wiring by name you can also use

@Resource(name = "id")
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Daff
  • 43,734
  • 9
  • 106
  • 120
2

The default mode of the @Autowired is byType.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
YJiao
  • 409
  • 4
  • 6
  • 3
    False, the default mode of the @Autowired is 'no' No autowiring is performed. All references to other beans must be explicitly injected. This is the default mode. – TheCyberXP Jan 02 '15 at 18:09
  • 4
    You refer to autowire attribute which is 'no' by default, @Autowired annotation is byType – jarosik Sep 29 '16 at 08:51
  • @TheCyberXP I think you have a slight misunderstanding here. The default mode of Spring's traditional XML-based configuration is 'no' i.e no auto wiring is enabled by default. But, if you choose to use annotation-based configuration(), & for instance, if you are using `@Autowired`, then the default method of auto wiring for this is "byType". For more clarity, you can refer [this link](https://howtodoinjava.com/spring-core/spring-beans-autowiring-concepts/) or [this link](https://www.baeldung.com/spring-autowire). Thanks. – Aniket Jun 23 '21 at 22:11
2

Autowired annotation on variable or setters method is equivalent to xml attribute autowire="byType"

XML attribute autowire is defaut as no

"no": 

The traditional Spring default. No automagical wiring. Bean references
must be defined in the XML file via the <ref/> element (or "ref"
attribute). We recommend this in most cases as it makes documentation
more explicit.
sendon1982
  • 9,982
  • 61
  • 44
0

These are no, byName, byType, constructor, and autodetect. The default mode is no i.e. by default autowiring is turned off in traditional XML based configuration.

Using @Autowired annotation-

1) @Autowired on properties:

When @Autowired is used on properties, it is equivalent to autowiring by byType in configuration file.

2) @Autowired on property setters:

When @Autowired is used on setters, it is also equivalent to autowiring by byType in configuration file.

3) @Autowired on constructors:

When @Autowired is used on bean’s constructor, it is also equivalent to autowiring by constructor in configuration file.

Use @Qualifier for conflict in dependency resolution

As we learned that if we are using autowiring in byType mode and dependencies are looked for property class types. If no such type is found, an error is thrown. But, what if there are two or more beans for same class type.

In this case spring will not be able to choose correct bean to inject into property, and you will need to help the container using qualifiers.

To resolve a specific bean using qualifier, we need to use @Qualifier annotation along with @Autowired annotation and pass the bean name in annotation parameter.

harit
  • 33
  • 6
0

I just checked out the source code of the spring-beans-5.2.7.RELEASE.jar. It contains class DefaultListableBeanFactory with the method

@Nullable
    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }
        String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        }
        // Fallback
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateName = entry.getKey();
            Object beanInstance = entry.getValue();
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }

As we can see it tries to autowire by type. If no success it tries to autowire by name in this line

matchesBeanName(candidateName, descriptor.getDependencyName()))
Sabfir
  • 186
  • 4
  • 5