Search code examples
javaspringspring-mvcinversion-of-controlioc-container

Constructor-Based Dependency Injection within Spring


I have this class:

@Service
    
public class DogUserService  {
    
         
private final ManagerService managerService;
...
}

and on my context.xml:

   <bean id="managerService"
        class="com.dogs.impl.services.ManagerService" />

but when I run the app. I have this error:

    rvice.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'com.dogs.impl.services.ManagerService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency a
    nnotations: {}

Solution

  • You need to provide the bean using @Bean annotation to the WebApplicationContext. I have created the managerService bean from context.xml within a @Configuration bean and made the bean available in webApplicationContext with @Bean method. This UserService class which has managerService as autowired has the property @ConditionalOnBean for this configuration bean.

    Below is how I have implemented it.

    Application class

    @SpringBootApplication public class DemoApplication
    {
    
        public static void main(String[] args)
        {
            SpringApplication.run(DemoApplication.class, args);
        }
    
    }
    

    UserService

    @Service
    @ConditionalOnBean({EnableConfiguration.class})
    public class UserService
    {
        @Autowired
        private ManagerService managerService;
        
        public String run() {
            System.out.println("Going to Run from manager Service");
            return managerService.run();
        }
    
    }
    

    EnableConfiguration

    @Configuration
    public class EnableConfiguration implements InitializingBean
    {
    
        ManagerService managerService;
    
        @Bean
        public ManagerService mngrService() {
            return managerService;
        }
    
        @Override public void afterPropertiesSet() throws Exception
        {
            ApplicationContext ctx = new ClassPathXmlApplicationContext( "context.xml" );
            managerService = (ManagerService) ctx.getBean("managerService");
            System.out.println("manager bean:" + managerService.toString());
            mngrService();
    
        }
    }
    

    ManagerService

    public class ManagerService
    {
        private int a;
        private int b;
    
        public ManagerService(int a, int b) {
            this.a = a;
            this.b = b;
        }
    
        public String run() {
            return this.toString();
        }
    
        @Override public String toString()
        {
            return "ManagerService{" + "a=" + a + ", b=" + b + '}';
        }
    }
    

    ServiceController

    @RestController
    public class ServiceController
    {
        @Autowired
        private UserService userService;
    
        @GetMapping("/get")
        public String test() {
            return userService.run();
        }
    }
    

    context.xml

        <bean id="managerService" class="com.example.demo.ManagerService">
            <constructor-arg index="0" value="2"/>
            <constructor-arg index="1" value="5"/>
        </bean>