Skip to content

Dependency injection

  • The client delegates to call to another object the responsability of providing its dependencies
  • Injection types
  • Constructor injection
  • Setter injection

XML

 <!-- Load properties file -->
<context:property-placeholder location="classpath:sport.properties" />

<bean id="myFortuneService"
      class="com.hvitoi.fortune.HappyFortuneService">
</bean>

<bean id="myBaseballCoach"
      class="com.hvitoi.coach.BaseballCoach">

    <!-- constructor injection-->
    <constructor-arg ref="myFortuneService" />

    <!-- setter injection. -->
    <property name="fortuneService" ref="myFortuneService" />

    <!-- set up literal injection -->
    <property name="emailAddress" value="[email protected]" />

    <!-- set up property file injection -->
    <property name="emailAddress" value="${foo.email}" />
</bean>
public class BaseballCoach implements Coach {
    private FortuneService fortuneService;

    // constructor injection
    public BaseballCoach(FortuneService theFortuneService) {
        fortuneService = theFortuneService;
    }

    // setter injection
    public void setFortuneService(FortuneService fortuneService) {
        System.out.println("CricketCoach inside setter method");
        this.fortuneService = fortuneService;
    }

    // literal injection - get
    public String getEmailAddress() {
        return emailAddress;
    }

    // literal injection - set
    public void setEmailAddress(String emailAddress) {
        System.out.println("CricketCoach inside setter method - setEmailAddress");
        this.emailAddress = emailAddress;
    }

    // Call method of the dependency
    @Override
    public String getDailyFortune() {
        // use my fortuneService
        return fortuneService.getFortune();
    }
}
  • Properties file

Annotations

  • Autowiring will automatically inject the dependency with the name provided in the constructor
  • @Autowired annotation on such a constructor is no longer necessary if the target bean only defines one constructor to begin with. However, if several constructors are available, at least one must be annotated to teach the container which one to use.
<beans>
    <!-- enable component scanning -->
    <context:component-scan base-package="com.hvitoi" />

    <!-- Load properties file -->
    <context:property-placeholder location="classpath:sport.properties" />
</beans>
package com.hvitoi.springdemo;

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

// @Component annotation registers the class as a spring bean In quote is the bean ID
@Component
public class TennisCoach implements Coach{

    // field injection - reflection
    @Autowired
    @Qualifier("happyFortuneService") // @Qualifier must be specified when there are multiple implementations for a interface. It tells which implementation to pick (by its bean id)
    private FortuneService fortuneService;

    // Property file injection
    @Value("${foo.email}")
    private String email;

    @Value("${foo.team}")
    private String team;

    // Default constructor
    public TennisCoach() {
        System.out.println(">> inside default constructor");
    }

    // constructor injection
    @Autowired
    public TennisCoach(@Qualifier("randomFortuneService") FortuneService fortuneService) { //  qualifier optional
        this.fortuneService = fortuneService;
    }

   // method injection
   @Autowired
   public void doSomeCrazyStuff(FortuneService fortuneService) {
       System.out.println(">> TennisCoach: inside doSomeCrazyStuff()");
       this.fortuneService = fortuneService;
   }

   // setter injection
   @Autowired // Substitute the constructor for dependency injection
   public void setFortuneService(FortuneService fortuneService) {
       System.out.println(">> TennisCoach: inside setFortuneService");
       this.fortuneService = fortuneService;
   }



    // Call method of the dependency
    @Override
    public String getDailyFortune() {
        return fortuneService.getFortune();
    }
}

Java code

@Configuration
//@ComponentScan("com.hvitoi.springdemo")
@PropertySource("classpath:sport.properties") // inject property file
public class SportConfig {
    // Register bean
    @Bean
    public FortuneService sadFortuneService() {
        return new SadFortuneService();
    }

    // Register bean with dependency
    @Bean
    public Coach swimCoach() {
        return new SwimCoach(sadFortuneService());
    }


}
public class SwimCoach implements Coach{
    private FortuneService fortuneService;

    // ---
    @Value("${foo.email}")
    private String email;

    @Value("${foo.team}")
    private String team;

    public String getEmail() {
        return email;
    }

    public String getTeam() {
        return team;
    }
    // ---

    public SwimCoach (FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }

    @Override
    public String getDailyWorkout() {
        return "Swim 1000 meters as a warmup.";
    }

    @Override
    public String getDailyFortune() {
        return fortuneService.getFortune();
    }
}
public class SwimJavaConfigDemoApp {
    public static void main(String[] args) {
        // read spring config java class
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SportConfig.class);

        // get bean from spring container
        Coach theCoach = context.getBean("swimCoach", Coach.class);

        // call method
        System.out.println(theCoach.getDailyWorkout());
        System.out.println(theCoach.getDailyFortune());

        // close context
        context.close();
    }
}