Transcript for:
Understanding Dependency Injection with Spring

foreign [Music] welcome back in the previous video we have seen how using dependency injection helps us write in unit tests and also we have seen how we can switch different implementations based on the configuration in this video we are going to use spring to do the dependency injection and then we will learn how springs dependency injection Works behind the scenes here I have a simple Maven project with the same code we have used in the previous video but it is not a spring boot application it's a simple man project and we just have spring context added as a dependency it started spring boot based application and we have the same code base like we have I background verification service interface and then there are two implementations of it and we have Loan Service which is taking High background verification service as a dependency through Constructor and we have applied for loan method and we have a simple bin loan request with few properties and here is our main application just assume we are building a simple console application and we need to get an instance of loan service and then we constructed a loan request and then finally called apply for loan and based on this code we are going to either get approved or rejected so here how do we get an instance of loan service so we are going to use Spring's dependency injection and then we will get the bin out of Springs application context so in order to do that what we need to do first we need to annotate our beans with the at component annotation [Music] and for this example I want to use background verification service so here I have already added at component annotation and how do I create application context because I want to use annotation based approach so I can create annotation config application context [Music] and create here I can pass what are the base packages I want spring to scan and identify the pins so here I would pass thumb dot Seva labs.di so that is where all my code in so I am going to pass that as a base package so once I have this application context I can look up the bin context dot get pin and I want loan service.class type bin foreign [Music] service object and I have loan request and then I am calling for apply for loan and let us see so here we can see loan is approved because I am giving my unique IDP one zero zero and as per our configuration it's going to use this background verification service and here I am simply returning to and in loan service if the score is less than 3 it's going to be sanctioned and return true so that's why we can see loan is approved so it is as simple as that by using Springs dependency injection capabilities we simply mark down veins as spring components using annotation and we also annotated at component to our dependent mean so spring is going to figure out okay I need to create a bin of background verification service and then I need to create a be enough loan service and then inject through Constructor okay it works so we have used spring and we have added couple of annotations to our beans and then we created an application context specifying the base package and we are able to get our loan service pin looking up from the application context and it is working fine but how exactly it is working and how spring is able to do this dependency injection so let us understand the inner workings of Springs dependency injection so that we'll have a better understanding of how a spring dependency injection work okay you may ask why should I bother to learn inner workings of a framework why can't I simply just use it and then move on why should I land so the reason is spring and spring boot is a large ecosystem of modules but Springs dependency injection is a very core concept and you will be using that throughout the modules like you will be using that irrespective of whether you are using spring data Spring Security spring MBC and a plenty of other models so this is a very core concept and getting a good idea about how springs dependency injection works is going to really help you to understand other modules which are depending on this core spring dependency injection very very much so I am going to go deep dive into how spring is doing this dependency injection behind the scenes before exploring how spring is doing a dependency injection let us think for ourselves for a minute how would I Implement dependency injection if I was supposed to implement this feature this framework okay so here we have annotated our beans with some annotation okay and how do I make these beans instances and then inject that instance into this load surface okay so the way I would think is first let me write down here so first I would scan all the classes which content and identify [Music] which classes has add component annotation okay so first I am going to read through all the source code in our project and then see which classes has at component annotation because those are the bins we need to instantiate and let's assume we we scan through all this code and then we identified okay we have loan service and we have background verification service these are the two components that we need to create and also first we need to create an instance of background verification service and then we need to instance loan service by passing that instance to this Constructor right so how do we know first we need to create this background verification service and then we need to create loan service it's using reflection so here once we identify all the beans what we can do we can identify the mean dependencies using Java Reflection [Music] so this Java Reflection using Java Reflection what we can do we can inspect the metadata about any classes what I mean by metadata like I can at runtime I can take any class and I can see what are the properties are defined for that class and what are the constructors defined for the class and what are the methods that are defined for the class and what are the modifiers it has so I can get all this metadata about any class using Java Reflection API so once I identify all the beans that has at component annotation I can use Java Reflection to identify what are the dependencies each component has so here I can see background verification service and I can see okay it doesn't have any other dependencies and I can see loan service and I can read what are all the constructors defined in this class and what are the types of dependencies it is expecting okay using Java Reflection once we identify the dependencies we can kind of follow this recursive approach okay first if I try to create a loan service object first I can see it needs a b and off type background verification service and then first I try to instantiate background verification service and here it doesn't depend on any other beads so I can instantiate this an instance for background notification service how again using Java Reflection API we can use reflection API and create an instance of it and uh whether it has any inputs uh through Constructor or without any inputs we can use our reflection API and create an instance of it once I create this instance I can go back in that recursion cycle and then try to create an instance of loan service bypassing that a background of recreation service instance to this okay so that is how the third step would be create instances of the beads using reflection API so this way I can instantiate all the required beams and then create a full full-fledged application context having the fully instant instantiated bin hierarchies let us start understanding how spring is scanning all the classes and identify which classes has at component annotation so let us create a class cards spring delay and create a main method [Music] and here we have class path scanning candidate component provider provided by Spring no wonder there are jokes on Springs long class names okay let us instantiate this class and here we need to specify should we use default filters or not so what does that default filters means okay so by default the string has the score annotation of add component right and then there are more specific variations like this at repository at service at controller like that but the base component is at component the base annotation is at component so by specifying true it's going to read all the classes that is having at component but if you are looking for any specific annotation what you can do we can pass false which means it is not going to look for at component and then you can specify exactly what annotation you are looking for by using scanner dot add inclusion filter new annotation type filter and let's say we are looking for component head component annotation right we can specify let's say if we are creating our own annotation we can pass okay my component or whatever annotation that you are looking for so after specifying this inclusion filter what we can do scanner Dot find candidate components and here we need to specify base package or total spring where to look for the Peaks so here I am going to specify look in this com.ceverlabs.di package and what it is going to return it's going to return a set of Bin definitions what does a bean definition has let us first iterate and then print transaction foreign [Music] has a lot of information about each of those components components in the sense a beam so here we can see what is the bin class name and one being can Define depend on other beans and what are the Constructor argument values and there are lots of information metadata information spring is already scanning and holding it is it a prototyping is it a single time being so like that you have a plenty of information scanned and hold so here first let us simply print is [Music] okay so let us run this so it identified there are two beans which are string components background verification service and Loan Service how because we annotated them with ADD component Okay so this spring utility class class path scanning candidate component provider help us to identify what are all the beans that are annotated with at component annotation and we specified where to look for the pins so that is how spring is able to identify what are the potential Spring components that it is going to create the instances for it okay so this is step one identify all the classes that has at component annotation so the next step would be identify the beam dependencies using Java Reflection so it is going to do internally it has lots of implementation but let us simply see how we can use Java Reflection API and identify what are the constructors each of these pins have okay okay I'm going to move all this code into a separate method foreign [Music] what are all the constructors a class has using Java Reflection API so let us create static void print Constructors so we are going to specify what is the class we are interested in right [Music] okay so how do we get Constructors of Any Given class using Java Reflection APK so what we can do type Dot get Constructors we can call get Constructors to return what are all the available Constructor because there can be one or more Constructors in a class so it's going to return an array of Constructors and here let's assume in our case just we have only one Constructor and let us Constructors take the first one and get what are all the parameters it has get parameters so if you look at a Constructor here it has one parameter of certain type right so we just got get Constructors that means it's going to return one Constructor and then we are trying to fetch what are all the types of parameters it has so here by calling this cat parameters it's going to return a parameter array so in our case suppose if we pass to this method if we pass loan service it's going to return one Constructor and it's going to have one parameter of type High background verification service so here if we iterate over parameters foreign [Music] for now let's just print what are all the constructors we have and print each parameter type [Music] so let us call Print Constructor and I'm going to pass loan service class [Music] thank you if I run it now so here it says parameter type of interface of this particular type I background verification service so that is how we can do identify the pin dependencies using Java Reflection so here this is how I can identify what are all the dependencies for a given class so let's say if I specify background verification service okay so here it's not going to print anything because it doesn't have it doesn't have any dependencies here we don't have any Constructors defined that means it's going to have a default Constructor without any parameters that's why we are not seeing any parameters over here so that is how we can identify what are all the dependencies a particular bin has using reflection API like this let's say if we is loan service and in loan service we not only have a High background verification service let us say we have another class called loan Repository [Music] okay and here again I am going to annotate with ADD component and I am going to add it as a dependency of loan service [Music] start phone deposit is equal to loan deposit okay now if I go back to our main method so spring TI class here if I pass Loan Service earlier we have seen only one parameter of type background verification service now if I run again it's going to show there are two dependencies one is of type I background verification another one is of type loan repository so that is how you can identify what are all the dependencies a bin has using Java reflectioning here okay so the next part is how to create instances of beans using reflection API okay so let us go back to our spring da so here I am going to comment out this method curl and create a new method called create beans using reflection [Music] so here what I'm going to do is I want to create an instance of loan service but before that I need to create an instance of background verification service and Bone repository and then pass those instances to loan service right but I'm going to do all this using reflection API so first we need to class start for name and then specify fully qualified name of the class that we are going to create so here I am going to give background verification service start class start get name and it's going to load this class and here I am going to call get declared Constructors so here a class may have one or more Constructors but in our case we did not specify any Constructors explicitly for background verification service which means there is a only a default Constructor so I am going to take the first Constructor and then call new instance if your class is taking any Constructor arguments we need to specify those arguments here but here we don't have any arguments for background verification service Constructor so I'm not going to call plus any values here so first let us declare it as throws exception okay and here it's going to return an instance of background verification service background verification service okay but it's a generic method call it's going to return uh generic object so we need to type cast it so I'm going to cast it to background verification service okay so now we have an instance of background verification service the next thing is we need to create an instance of loan repository as well because our clone service has a dependency and Loan repository as well so again create in the same way class start funny loan repository dot start get name dot get declared Constructors and again we don't have any Constructors over there so I'm going to call new instance [Music] and it's going to return loan Repository [Music] I'm going to cast it to loan Repository okay we have both background verification service and Loan repository we are going to follow in the same way class start for name and this time it's going to be Loan Service dot class dot get name and you can declared Constructor and again because we explicitly defined a Constructor it's not going to have any uh default Constructor so we know there will be only one constructed so I'm going to take the first Constructor and then call new instance but here I need to pass the expected dependencies for the Constructor we already have background verification service and Loan repository so I am going to pass to this new instance method and here it's going to return a loan service instance [Music] okay [Music] fine but are we sure it's it's going to work fine let us test that let's call this function and I can just stick it through exception and let us go back to our main method and take this [Music] go back and here so here we have Loan Service instance created via reflection API and we created a loan request and then calling apply for loan so I'm going to call this nothing yes it is working fine right so that's how okay let us verify what if I want to change background verification service to use mock background notification service okay let us try that go back and instead of this okay so here I used mock background verification service instead of background verification service and here if I call loan is approved but according to the behavior if I pass anything apart from this unique IDs it should result right let us verify that by changing the unique ID from p100 to P 200 and then run it so now loan is rejected so we are sure that it's going it is using mock background verification service Okay so now coming back to our three points so this is how we can use reflection API and create the instances according to our names so these are all the background implementations spring is doing like it is scanning all the classes and then identifying the beams that are having at component annotation and then we have seen how we can identify what are all the dependencies a bean has using server reflection and then once it identifies those dependencies it can use the reflection API to create those instances and then pass those instances to create the instance so spring is heavily using that reflection API to do all these things in the background and then it is creating all these full Fred's services and then providing them via our application context so these are all the things that is happening behind the scenes and we are simply able to create annotation application context and then specifying this package and it is doing all this behind the scenes and we are able to Simply call just give me whatever the bin I want and it is going to Simply return that theme so this is how spring is doing all this annotation magic behind the scenes and then instantiating all these classes using Java Reflection API and providing us the full-fledged constructed Fields so we have seen how spring is doing the dependency injection and how behind the scenes it is using reflection API and its own lot of annotation processing logic to fully construct the beams required beans but the question is in order to follow the dependency injection design pattern should we always rely upon some framers like spring of course not just as we have seen it's not really any magic uh it's kind of an approach how you instantiate a dependencies by passing the dependent objects to it instead of constructing its own dependencies in the class directly so we don't even need to use any framework let's say we are building a small application and we hardly have a handful of classes like 10 or 20 and we don't want to have overhead off using heavyweight Frameworks so can't we do dependency injection no we can't do that uh in fact let us try to create our own Bean Factory and then see how we can create a similar bin Factory just like the way we have here annotation config application context right let us create our own bean factory and see how we can do that okay so first let me create my Bean Factory so here we are not going to use all this reflection magic and everything because our application is small and we know what instances we need to create and in what order so I'm going to straight away create the pins that are required only for my application I am not going to create a generic implementation of dependency injection container over here so let us see how we can do this without having to use any framework so I am going to create a map private map which holds class type as the key it can be any object as a value and let me name it as beans and here I am going to call a method to initialize this map [Music] okay so here I'm going to create Bean map and initialize it and I'm going to return it okay so because I know what classes I have in my application and I know the order I need to create I'm going to just create using planes Java code like okay first I want to create an eye background verification service and I'm going to use mock background verification service and next I need loan Repository I'm going to create new loan repository next I need to create loan service [Music] new loan service and pass background verification service and Loan repository as dependencies but before that I am going to put those beans in so if it is I background verification service class I am going to store background verification service implementation again I'm going to use and for loan repository type I'm going to put loan repository similarly for loan service I am going to put Loan Service as the object of value so here once I have initialize this map and then instantiated all the objects that I need for my application and then store each type along with its value and now I can expose a method like public it's going to be a typed value and get pin and specify what type I want and here I'm going to return from beans start get of the type but it's going to be a generic one so I'm going to type casted to T okay so this is how I simply created my bin Factory so now if I go back to our main method instead of using annotation config application context and creating Loan Service like this what I will do I'm going to create an instance for my bin Factory [Music] and I'm going to create a Zone service by looking up we in Factory dot get pin off type loan service class okay so here I am going to run this and then see loan is approved and if I change it to P 200 it's going to project alone so it is as simple as doing like this but for smaller application you can still follow dependency injection because there are only a handful of classes and then you know the order to create and then you can hold the beans and wherever you want to maybe you might want to make it as a Singleton class and then return whenever somebody asks for a bin you simply written that so the point is in order to use the dependency injection pattern you don't have to always rely upon Frameworks like spring or anything if it is a small project and you don't want to use any heavyweight framers you still follow the pattern so the idea is you don't instantiate the dependencies directly in the class itself you take them as a Constructor arguments so that you give an opportunity for the a third party framework like spring or another utility that can create the instant chances and then pass it to the components as a Constructor arguments so that there is a flexibility how you want to construct your object you are giving an opportunity to other Frameworks or utilities to construct in a different different ways here I can just read from a configuration file and then decide which implementation I want to use I want to use mock pin background verification service or I want to use this actual background verification service I can read some configuration file and then decide which implementation I want to use so the idea is do not directly instantiate your dependencies here instead take them as Constructor arguments that is the key point of dependency injections we have talked about what is the dependency injection and how to do the dependency injection using spring and how we can roll out our own uh dependency injection If the product is small and with only a handful of classes and what is the purpose of using dependency injection in the first place so but there is a lot more to what spring has to offer like right now we simply annotated with that component and by default it's going to create it as a single thumb pin and you can customize a lot of things like you can change the scope to instead of single turn you can make it as a prototyping and there are you can mark it as a lazy Bean so there are a lot more customizations you can do but we are going to learn about these additional features in the future videos okay so for now I think we have a good idea on dependency injection now and we are going to see what are all the other design patterns that spring is leveraging behind the scenes in the upcoming videos thanks for watching and stay tuned for the upcoming videos bye [Music]