Section 8 Flashcards
Create a application using Constructor injection and annotations. The application should print two methods: getDailyWorkout() and getDailyFortune()
//application context file content for scanning components
//Coach interface public interface Coach {
public String getDailyWorkout(); public String getDailyFortune();
}
//TennisCoach class that implements Coach @Component("tennis") public class TennisCoach implements Coach {
private FortuneService fortuneService;
@Autowired public TennisCoach(FortuneService fortuneService) { this.fortuneService = fortuneService; }
@Override public String getDailyWorkout() { return "Practice your backhand volley"; } @Override public String getDailyFortune() { return fortuneService.getFortune(); }
}
//FortuneService interface public interface FortuneService {
public String getFortune();
}
//HappyFortuneService class that implements FortuneService @Component public class HappyFortuneService implements FortuneService {
@Override public String getFortune() { return "Today is your lucky day!"; }
}
//Main class public class Main {
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("file:src/main/java/com/springboot/annotations/applicationContext.xml");
Coach coach = context.getBean("tennis", Coach.class); System.out.println(coach.getDailyWorkout()); System.out.println(coach.getDailyFortune()); context.close(); }
}
In previous example was necessary to use @Autowired annotation on TennisCoach constructor ?
@Autowired public TennisCoach(FortuneService fortuneService) { this.fortuneService = fortuneService; }
After spring 4.3 version the @Autowired annotation is no longer necessary if using a single constructor, if using several constructors then is necessary.
Create a similar application with first one, but this time instead using constructor injection, use setter method injection.
//application context file content for scanning components
//Coach interface public interface Coach {
public String getDailyWorkout(); public String getDailyFortune();
}
//TennisCoach class that implements Coach @Component("tennis") public class TennisCoach implements Coach {
private FortuneService fortuneService;
public FortuneService() { }
//Autowired will inject FortuneService dependency into TennisCoach //using setter method @Autowired public setFortuneService(FortuneService fortuneService) { this.fortuneService = fortuneService; }
@Override public String getDailyWorkout() { return "Practice your backhand volley"; } @Override public String getDailyFortune() { return fortuneService.getFortune(); }
}
//FortuneService interface public interface FortuneService {
public String getFortune();
}
//HappyFortuneService class that implements FortuneService @Component public class HappyFortuneService implements FortuneService {
@Override public String getFortune() { return "Today is your lucky day!"; }
}
//Main class public class Main {
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("file:src/main/java/com/springboot/annotations/applicationContext.xml");
Coach coach = context.getBean("tennis", Coach.class); System.out.println(coach.getDailyWorkout()); System.out.println(coach.getDailyFortune()); context.close(); }
}
@Autowired functioneaza doar cu metodele setter clasice sau cu orice metoda ?
@Autowired functioneaza cu orice metoda.
Which is the simplest way to inject FortuneService into TennisCoach ?
Using Feld Injection:
//this way there is no need for any constructor or setter method, java will do all the job in background using reflection technology. So this example should give the same result as constructor injection or setter injection
@Autowired
private FortuneService fortuneService
Which of the following injection types is recommended to use ?
- Constructor injection
- Setter injection
- Field injection
They are all the same, the do the same functinallity in the background…so the easiest one is field injection because there are less lines of code to write.
Let’s say instead of HappyFortuneService we have another 3 classes that implements FortuneService:
- RandomFortuneService
- DatabaseFortuneService
- RESTFortuneService
This will give a error because the program does not know which of this 4 FortuneServices should use, so how we tell the program which of them to use ?
We add the annotation @Qualifier
@Component public class TennisCoach implements Coach {
@Autowired @Qualifier("happyFortuneService") private FortuneService fortuneService; public TennisCoach() { } @Override public String getDailyWorkout() { return "Daily workout method"; } @Override public String getDailyFortune() { return fortuneService.getFortune(); }
}
So we add as @Qualifier parameter the id of the fortuneService we want to use
If there isn’t specified a id for a component, the name of the class will be used but with lowercase of the first letter like this:
HappyFortuneService - id = happyFortuneService.
But what id will have RESTFortuneService ?
If the name of the class has 2 uppercases as first and second letter, then the name will not be converted and will remain the same
RESTFortuneService - id = RESTFortuneService
What happens when you try using @Qualifier annotation on constructor ?
@Qualifier annotation is not working in the standard way like this:
public TennisCoach(FortuneService fortuneService){ this.fortuneService = fortuneService; }
but will work like this:
@Autowired
public TennisCoach(@Qualifier(“randomFortuneService”) FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
Create a application SwinCoach, where dependency injection in fields are read from a file.
ex: email and team fields
//SwinCoach class @Component public class SwimCoach implements Coach {
@Autowired @Qualifier("randomFortuneService") private FortuneService fortuneService; @Value("${foo.email}") private String email; @Value("${foo.team}") private String team; public SwimCoach() { } @Override public String getDailyWorkout() { return "Swin 1000 meters as a warm up."; } @Override public String getDailyFortune() { return fortuneService.getFortune(); } public String getEmail() { return email; } public String getTeam() { return team; }
}
//sport.properties file content
foo. email=myeasycoach@luv2code.com
foo. team=Silly Java Coders
//applicationContext.xml file content
//Main method public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("file:src/main/java/com/springboot/annotations/applicationContext.xml");
SwimCoach coach = context.getBean("swimCoach", SwimCoach.class); System.out.println(coach.getDailyFortune()); System.out.println(coach.getDailyWorkout()); System.out.println(coach.getEmail()); System.out.println(coach.getTeam()); context.close(); }
Create a new FortuneService implementation that will read field values from a file and then create an array where field values will be inserted. Finally display a random value from the array.
//GymFortuneService class @Component public class GymFortuneService implements FortuneService {
@Value("${foo.fortuneOne}") private String fortuneOne; @Value("${foo.fortuneTwo}") private String fortuneTwo; @Value("${foo.fortuneThree}") private String fortuneThree; private Random random = new Random();
@Override public String getFortune() { String[] data = { fortuneOne, fortuneTwo, fortuneThree}; return data[random.nextInt(data.length)]; }
}
//applicationContext.xml content
//sport.properties file content
foo. fortuneOne=Lucky
foo. fortuneTwo=Not lucky
foo. fortuneThree=Verry lucky
//Main method public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("file:src/main/java/com/springboot/annotations/applicationContext.xml");
GymFortuneService fortune = context.getBean("gymFortuneService", GymFortuneService.class); System.out.println(fortune.getFortune()); context.close(); }