Ensured that all this basic stuff works properly, I can confidently move to something more interesting. Let's say hello using IoC (Inversion of Control) and DI (Dependency Injection).
I create a dedicate package for the logic related stuff for my hello project. Not surprisingly, I name it logic, and I put it under the hello package.
Actually, there's not much logic in this app, I just want to greet users. This suggests me to create an interface, Greeter, that exposes the a single greeting method.
The GreetingController changes accordingly. I remove the logic in it, delegating the work to the actual class that is going to implement the Greeter interface.
Notice how much more cleaner is this way of working. The controller doesn't know anymore about how a greeting is generated. It just knows that exists a Greeter interface, it holds a reference to it that is annotated as a Resource, a javax annotation, and through it, a greeting() method would be called to answer to the user request.
I create a couple of concrete classes implementing Greeter to give a sense to this architecture. There are about identical, in the real world things are usually more complicated. Here is the PlainGreeter, its brother MockGreeter is about the same.
Notice how the relation between the controller and the concrete Greeter is set. Before IoC it was commonly considered a controller task to define a dependency with the Greeter. In a way or another, an instance of the actual Greeter was created and used. Now IoC rules, so we perform an Inversion of Control. Is the Greeter that signal to be available for the controller, and the framework, Spring here, that take care of making it work.
I use annotation to implement the IoC relation, and you can see how in the code.
In the controller I have annotated its Greeter data member as Resource. This javax annotation tells Spring that Dependency Injection should be used here.
Each concrete class implementing the Greeter interface that could be a target for DI should be marked as Component, a springframework stereotype annotation.
Finally, we have to tell Spring which among the available Components should be injected in the controller Resource.
An handy way to do it is combining configuration and annotation. In the Spring configuration file I specify which profile is the active one
spring.profiles.active=prodThen, I add a springframework context Profile annotation to each component, marking with the active profile only the one I want to be used. Be careful on it. Here is the exception that I get at startup if I mark both my components as "prod":
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'greetingController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'dd.manny.hello.logic.Greeter' available: expected single matching bean but found 2: mockGreeter,plainGreeter
This Spring Boot project is on github. You could be mainly interested in these files:
- GreetingController.java, modified to use a Greeter object annotated as resource;
- application.properties, in which I added the active profile property;
- the package logic; containing the Greeter interface and its two implementations.
No comments:
Post a Comment