SpringBoot: Refactoring new to bean, Parameter 0 of constructor required a single bean, but 2 were found
16:36 08 Jan 2026

I wrote this simple Spring Boot project:

package com.example;

//just a simple interface, nothing spring-related here
public interface Foo {

    String addFoo(String foo);

}
package com.example;

//just a simple implementation, nothing spring-related here
public class FooImpl implements Foo {

    @Override
    public String addFoo(String foo) {
        return "this is a foo WITHOUT dependency injection: " + foo;
    }

}
package com.example;

// just a simple interface, nothing spring-related here
public interface MyThing {

    Foo foo();

}
package com.example;

//just a simple implementation, nothing spring-related here
public class MyThingImpl implements MyThing {

    private final FooImpl fooImpl;

    public MyThingImpl(String importantConfiguration) {
        System.out.println("this layer needs to get the @Configuration value to perform its logic: " + importantConfiguration);
        fooImpl = new FooImpl(); //using "new" keyword here!
    }

    @Override
    public Foo foo() {
        return fooImpl;
    }

}
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

    public static void main(final String[] args) {
        SpringApplication.run(MyApplication.class);
    }

}
package com.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

    @Value("${my.important.configuration}")
    private String importantConfiguration;

    @Bean
    public MyThing myThing() {
        // need to configure MyThingImpl bean with importantConfiguration from this layer
        return new MyThingImpl(importantConfiguration); //using "new" keyword here!
    }

}
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
public class TestingSolutionOne {

    private final MyThing myThing;

    @Autowired
    public TestingSolutionOne(MyThing myThingParam) {
        // here, we inject the !configurable! MyThing bean via constructor injection
        this.myThing = myThingParam;
    }

    @GetMapping(value = "/test")
    public Optional mockFindById() {
        String firstResult = myThing.foo().addFoo("testFoo");
        System.out.println("First Result: " + firstResult);
        return Optional.of(firstResult + "-");
    }

}

And this is working perfectly fine. It is doing the business logic.

I am able to configure my bean with configuration, and on the controller layer, to get it and perform my business logic.

However, I am getting the following issues. We are using several static analysis tools, as well as AI code review tools, each from different companies than the others, in total 6 of them.

All came with the same following feedback:

  • The use of the keyword new here is an anti-pattern of Spring Boot. IoC, DI should be leveraged.

  • This implementation has memory issues over using Spring Boot bean design.

Failing to understand the feedback, I went to try to refactor to:

package com.example;

//just a simple interface, nothing spring-related here
public interface Foo {

    String addFoo(String foo);

}
package com.example;

import org.springframework.stereotype.Component;

@Component
// Now, I am marking this class as a Spring component
public class FooImpl implements Foo {

    @Override
    public String addFoo(String foo) {
        return "this is a foo WITH dependency injection: " + foo;
    }

}
package com.example;

// just a simple interface, nothing spring-related here
public interface MyThing {

    Foo foo();

}
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
// Now, I am marking this class as a Spring component, and FooImpl bean should be injected, no "new" keyword needed
public class MyThingImpl implements MyThing {

    @Value("${my.important.configuration:default}")
    private String importantConfiguration;

    private final FooImpl fooImpl;

    @Autowired
    public MyThingImpl(FooImpl foo) {
        System.out.println("I am not able to get the configuration from the @Configuration layer anymore, since I cannot 'new MyThingImpl(configuration)'' " + importantConfiguration);
        fooImpl = foo;
    }

    @Override
    public Foo foo() {
        return fooImpl;
    }

}
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

    public static void main(final String[] args) {
        SpringApplication.run(MyApplication.class);
    }

}
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

    //Think I am doing it wrong here, the configuration cannot be passed to MyThingImpl

    private final MyThing myThing;

    @Autowired
    public MyConfiguration(MyThingImpl myThingParam) {
        this.myThing = myThingParam;
    }

    @Bean
    public MyThing myThing() {
        return this.myThing;
    }

}
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
public class TestingSolutionTwo {

    private final MyThing myThing;

    @Autowired
    public TestingSolutionTwo(MyThing myThingParam) {
        this.myThing = myThingParam;
    }

    @GetMapping(value = "/test")
    public Optional mockFindById() {
        String firstResult = myThing.foo().addFoo("testFoo");
        System.out.println("First Result: " + firstResult);
        return Optional.of(firstResult + "-");
    }

}

While I think this is more "Spring like" (not sure, if you could help confirm), I am getting:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.TestingSolutionTwo required a single bean, but 2 were found:
    - myThingImpl: defined in file [/Users/question/target/classes/com/example/MyThingImpl.class]
    - myThing: defined by method 'myThing' in class path resource [com/example/MyConfiguration.class]

Question: How to properly refactor this into Spring like, and having the project work like solution one?

P.S. If possible, it would be great to highlight the drawbacks of solution 1. While I just blindly trust nd follow the analysers, I am having a hard time understanding what is the issue

java spring spring-boot spring-mvc