Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Autowired any method name with any number of arguments

Tags:

java

spring

I am trying to annotate a set method as follows:

package com.spring.examples;
public class MyBean
{
    private String name;
    private int age;

    @Autowired
    public void set(String name, int age)
    {
       this.name = name;
       this.age = age;
    }
}

the config file:

<bean id="myBean" class="com.spring.examples.MyBean">
    <property name="name" value="Marie" />
    <property name="age" value="101" />
</bean>

I got this error:

No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies

How can I configure this bean to properly call the set method?

like image 204
JoseA Avatar asked Jun 27 '13 21:06

JoseA


People also ask

Can we use @autowired on methods?

@Autowired can be used only on "a constructor, field, setter method or config method".

Can we do Autowired by name?

Autowiring Modes byName : The byName mode injects the object dependency according to name of the bean. In such a case, the property and bean name should be the same. It internally calls the setter method. byType : The byType mode injects the object dependency according to type.

Does spring @autowired inject beans by name or by type?

if Spring encounters multiple beans with same type it checks field name. if it finds a bean with the name of the target field, it injects that bean into the field.


Video Answer


1 Answers

It's OK to use @Autowired on a method with any number of arguments. The only problem is the application context must be able to identify what you want to inject for each of those arguments.

The complaint in the error message makes this quite clear: you don't have a unique String bean defined in your application context.

The solution for your particular example would be to use the @Value annotation for each of the arguments:

@Autowired
set(@Value("${user.name:anonymous}") String name, @Value("${user.age:30}") int age)

This will make use of a PropertyPlaceholderConfigurer defined in your context to resolve those properties and will fall back to the provided defaults if those properties are not defined.

If you want to inject objects that are defined as beans in your context, you only need to make sure there's only one matching bean for each argument:

@Autowired
set(SomeUniqueService myService, @Qualifier("aParticularBean") SomeBean someBean)

In the above example, the assumption is that there's only one instance of SomeUniqueService in the application context, but there may be several SomeBean instances -- however, only one of them will have the bean id "aParticularBean".

As a final note, this kind of usage for @Autowired is most suitable for constructors, as it's rarely the case where you need to set properties as bulk once the object has been constructed.

Edit:

I noticed your XML configuration after writing the answer; it's completely useless. If you want to make use of annotations, just define the bean without any properties and make sure you declare <context:annotation-config/> somewhere in your context:

<context:annotation-config/>
<bean id="myBean" class="com.spring.examples.MyBean"/>
<!-- no properties needed since the annotations will be automatically detected and acted upon -->

This way, the container will detect everything that needs to be injected and act accordingly. The XML <property/> element can only be used to invoke java bean setters (which only take one argument).

Moreover, you can annotate your class with a stereotype like @Component (or @Service or whatever) and then just use <context:component-scan/>; this would eliminate the need to declare each individual bean in XML.

like image 119
Costi Ciudatu Avatar answered Nov 11 '22 18:11

Costi Ciudatu