简体   繁体   中英

Spring creates two beans from one class using annotations

I have can create from two beans from one java class using xml configuration using following code:

    <context:component-scan base-package="some.package"/>

    <bean id="dependentBean" class="some.package.DependentBean">
        <property name="firstBean" ref="firstBean"/>
    </bean>

    <bean id="firstBean" class="some.package.Handler">
        <constructor-arg index="0" ref="service"></constructor-arg>
        <property name="defaultUrl" value="url/first"></property>
    </bean>

    <bean id="secondBean" class="some.package.Handler">
        <constructor-arg index="0" ref="service"></constructor-arg>
        <property name="defaultUrl" value="url/second"></property>
    </bean> 

My goal is move firstBean and secondBean to java based configuration like this:

package some.package;

@Configuration
public class Configuration {

    @Bean(name="firstBean")
    public Handler firstHandler(Service service){
        Handler handler= new Handler(service);
        handler.setDefaultTargetUrl("url/first");
        return handler;
    }


    @Bean(name="secondBean")
    public Handler secondHandler(Service service){
        Handler handler = new Handler(service);
        handler.setDefaultTargetUrl("url/second");
        return handler;
    }
}

But when context begins loading spring throws the following exception:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'firstBean' is defined

Nevertheless it works in this case:

package some.package;

    @Component
    public class Filter{

        private Handler handler;

        @Autowired
        public Filter(@Qualifier("secondBean") Handler handler) {
             this.handler = handler;
        }

    }

Handler implementation:

public class Handler {

    private Service service;

    @Autowired
    public Handler(Service service) {
        this.service = service;
    }

}

@Autowired is always by type. But you have two Handlers in your configuration. So when you try to autowire the handler class, you have to specify the qualifier. By this spring can resolve which instance to inject. Else, spring throws the error showing NoSuchBeanDefinitionFoundError . Expected one found two.

Hope that helps.

From the Spring Docs , section 5.9.3:

If you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if is technically capable of referring to a bean name through @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.

There's an example of this in section 5.9.5, but for your code, your Filter class should look like:

package some.package;

@Component
public class Filter {

    private Handler handler;

    @Resource(name="secondBean")
    public Filter(Handler handler) {
         this.handler = handler;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM