Transcript for:
Java Spring Dependency Injection

hello welcome to C snippet so in this video we are going to look into one of the important topic of java spring called as dependency injection there will be lot of interview questions that will be asked on this topic so let's see what it is so sit back relax and enjoy the show so let me bring in the agenda of today's video so spring dependency injection right so first we will see what are prerequisites that are required for this video after that we will see why dependency injection what is the need of it then we will see what is dependency injection and its types so there are basically three types field inje seter inje and Constructor inje right we will also discuss the advantages and disadvantages of these three right after that we will discuss the common problem that we face in dependency injection two of the most common problems are circular dependency and unsatisfied dependency so we will try to understand that by using a example so that is the agenda of this video so let's see what are prerequisites so basically in the last video I have covered the life cycle of bean and have covered what all stages the life cycle goes through and inject beans into constructed dependency is one of the step which a bean goes through right so if you haven't checked this video already just go and check it out this is the video basically where I have covered what exactly is the bean and how the life cycle of bean looks right so this video will be helpful to understand dependency injection as well so that is a prerequisite basically after that let's see why dependency injection right now let's jump into the code directly so this is basically a spring boot application right and I have I have this class over here so this is a simple class right so this is not a spring component or anything this is just a simple order class Java class I have one Constructor over here so let's say I have this user class over here and this user class is making use of order right so here in this scenario user is dependent on order right so we are creating object of order over here and then we are probably making use of it somewhere in the class and here is just a Constructor of this class right now this is a normal way how we create object of a class right so it shouldn't be a problem it should be fine but what is happening here is that user has a tight dependency on your order right so it is a tight coupling between both of them right so this tight coupling between these two might create some problem in future right so what problem it will create let's check it out so let's say we have a order class right so let's say we want to convert this to an interface in future and have a implementation of these so let's say we want to have online and offline order whose parent will be order right so what we will do here we will actually go ahead and convert it to interface let's remove this right now if I go inside user then it will throw error because we cannot instantiate the object of your interface right so that is a problem so let's say in future requirements if you are converting your classes to interfaces and have such a tight coupling then you cannot do that right you cannot create object of that interface now let's say there is online order class and and this online order class is implementing this order class right now how you can fix this error now here you can fix the error by using the instance of online order class over here which will solve the problem for you right now this will solve the problem but not entirely okay so here what we have seen user and Order classes have tied coupling right in future changes this might create a problem as we have seen right and now to overcome that problem we have provided a concrete implementation of this class right this is a class implementing order class right basically this is concrete implementation right so using this concrete implement ation of online order class here breaks one solid principle okay which solid principle it breaks dependency inversion right so dependency inversion is basically D inside your solid principle which says that do not depend on a concrete implementation of class rather go with your abstraction right so it says depend on abstraction rather than depending with your concrete implementation so it is saying don't use this concrete implementation rather just create object of order so what we need to do here we need to remove this just have a instance of your order class and take this order here inside your Constructor and initialize your order here saying this do order equals to order right so this is how you can ader to dependency inversion rule of your solid principle right now this dependency inversion can be achieved by dependency injection right so in Spring we can make these classes independent of these dependencies right we can we don't need to you know create uh this object here only saying new keyword right we don't need to do that what we can do is we can just declare this and we can inject the dependency dynamically right so this Dynamic dependency injection will be taken care by your ioc container right so so here this step inside your bean life cycle comes into picture right inject dependencies into constructed beans right basically we are avoiding any more tide coupling over here right so what we can do here is we can convert this class to component right and just add a auto wired annotation over here now we are getting error because uh we need to convert this implementation to component as well so I'll just add component here as well right so once I do that this will not throw any error right so that is how you can inject this order dependency inside your user class right so that is how you are adhering to your dependency inversion solid principle okay so that is how we can make use of Auto annotation and inject your dependencies inside your beans right now I'm using various annotations over here like component Auto right so if you have any doubt in any of The annotation right I have made a separate video on that so I'll just add a link in description you can go ahead and check that if you have any doubt in annotations right so that marks the end of why and how the dependency injection comes into picture right now let's check out what exactly is dependency injection so as we have seen injecting dependencies at runtime when whenever your application is coming up the dependencies will be injected right let's try and bring up this application and let's see if this statements are being printed on the console right so here as you can see here first we are initializing online order because that is the dependency for our user right and after that we are initializing user so these two beans are being initialized over here online order and user rate so that's how the dependency of your classes will be added now we can also debug this application and check so let me just add a debug point over here here so let me just start the application in debug mode here if you can see uh so my debug point is at this statement and at that point your order is filled with online order right so this instance of order is filled with online order class right so basically your spring is adding this dependency into user class right on runtime whenever your application is bringing up right so that is basically dependency injection right now let's jump to the types of dependency injection so dependency injection has three types first one is field injection second one is Setter injection and third one is Constructor injection so Constructor injection is very important and it's mostly used inside the IT industry basically it has more advantages than these two so that also we will discuss in this video so let's first go through field injection which is the first type of your dependency injection right so in field injection dependency is set on the field of a class right so this example that we have seen is a example of your dependency injection because this is a field of your use user class the order is a field of your user class and we are injecting it by using Auto right so this is something which we called as field injection basically right so what will happen at runtime if we run this application let's see so here we are first initializing order right so what will happen here as we have seen in Bean life cycle once the ioc container is initialized it will start constructing the beans right so it will check what all classes have component annotation right so it will come here to order and it will check okay component is a bean that we have to create what it will do it will create some object of this order let's say order by using this Constructor right so it will create this object while creating object it will call Constructor and that is when this output will be printed on the console right so spring has initialized this order and have that object ready inside your spring ioc container right now next it will encounter your user object now it will try to create a bean of this user object but it will see okay here we are Auto wiring a so user has a dependency on order as well so what will happen we already have this order inside your ioc container this order created so what spring will do spring will inject that order over here add that dependency over here right after that it will create the object of your user by using this Constructor right and that is when this statement will be printed on the console right so that is how this order dependency is being injected inside your user class right so that is how we can make use of field injection so it is very simple just add Auto annotation so any number of dependencies you can add over here that will be injected by your spring dependency injection right so basically spring uses reflection it iterates over the field of your glass and then inject the dependencies right so that is how it works right so any number of fields you have all those dependencies will be added provided that all those fields are your spring components and all the fields have at the Rate Auto annotation on top of them right so advantages of your field injection it's very simple and easy to use right you can just add at the rate autowire and the job is done right so let's see what are disadvantages of your field injection right so field injection cannot be used with immutable Fields what are immutable Fields let's say you mark something as final try to do it here what we will do here what we'll do we'll say public final order so the moment I do that as you can see we are getting some error because this final variable is not initialized right because we need to initialize this final variable when we declare it basically right or rather we need to initialize it in inside your Constructor right what is final variable basically so once you assign the value of your final variable you cannot change it later right let's say you have integer final variable and you have assigned the value of that variable to let's say five over here right so once you initialize it you cannot change the value if you try to change the value it won't permit you to change the value right so that is the use of basically final variable so basically final variable should be immutable variables right so that is the problem over here okay so that is the first problem that we encounter while using field injection right second problem is chances of null pointer exception over here so let's say here uh we don't have this final let's say we have this variable only right and let's say we have one method just simple method we are going to add over here and what we will do we will say order process order and the same method we will add inside our order class as well right and we'll just print something let's say that we are processing your order right so now let's say there is some other code okay let's say there is a main method over here now here what are we doing we are creating the instance of your user object right and we are calling user. process right now if I run this code let's see what happens so we are getting null pointer exception over here because we are creating the instance of user but this dependency is not actually injected because this code is not running from Spring right this is not a spring component we ran it explicitly right so in this case we don't know what is order because when we run it by using spring boot it will inject the dependencies but here we are not injecting the dependencies right we are just creating the user object this is the valid code right but when I call user. process as the process function is calling order this is giving us null pointer exception because order is empty right order is null basically so that is a second problem with your field injection so if someone writes a code like this inside your spring code then that is likely to break and throwing null pointer exception right so that is again a separate problem with your field injection right so basically these are two disadvantages of your field injection now let's proceed and see seter injection next so basically in seter injection we inject the dependency by using seter of that particular field right now let's see how so here um let's say we have order right so let's add a Setter over here so I'll add a Setter for order right and this Setter on top of this Setter what we are going to do we are going to add Auto and that's it this is a seter injection and we will remove it from here right and we have to annotate this method using autowire so that is something that we did already right so this is how you can use set injection basically now let's run this code and let's see what happens so so as you can see in the output the order and user are initialized right so that is how Setter injection we can use so instead of injecting your dependencies at the field level spring will now inject it by using Setters right so it will actually go ahead and check that there is a Setter method and there is a dependency injection annotation annotated that is autoed right and what needs to be injected over here the parameter which we are are going to pass over here which is order in this case so order object is already created here right so as we discussed while field injection this order will be created right so there will be a order object which will be present inside your ioc container so same object will be injected over here by using Setter and this uh this do order that means this order will be populated with that particular order which is coming from here which will be present inside your ioc container right so that is how it works basically and that we can see inside our output as well that your order is initialized and our user is initialized as well as both are spring components right now that is seter annotation and let's us discuss the advantages of seter injection now now dependencies can be changed at any point of time after object creation so let's say here once the object is created what we can do is we can call the seter method and we can inject other object as well right here for example what we can do here let's say we have online order here right so I'm just using this class to demonstrate so let's have let's say we have a main method what we can do here is main method or let's say you have any other function right so what we can do we can create object of user right let's say this is another user we can create object of order as well so this is a custom order not that order which is being injected inside your user right it is not this order which is present inside your ioc container right this order is different now this order what you can do you can say user dot set order and just inject this order order inside this user we are setting it explicitly right we can change the dependency at any point of time like that right and this is easy for junit testing as well we can pass mock objects independently so we can use Setter methods and you can pass the mock objects and set the mock objects explicitly right so that is also useful while you are doing junit testing right so that is another advantage of your seter injection after that let's discuss disadvantages Fields cannot be marked as final as we have seen inside field injection as well so cannot use immutable Fields right so same problem we will encounter in field injection as well that field cannot be marked as final right so let's see here so if I go inside here and let's say we mark it final right then it is giving us same error that we had in field injection that it's not able to initialize it so you cannot use seter injection when it comes to your immutable variables you cannot declare the final same as field injection right so here also it is giving us the error that this order is final and you cannot uh inject it right so that is one problem similar to field injection and another disadvantages is that this is difficult to read and maintain right so so basically if we have Auto wire here only we will know that this is being injected by Spring right but let's say we have it on Setter then we will need to find it okay where is the seter method and we'll need to check if it is auto wied or so the readability is the problem here right so it's difficult to find so it's not according to the standards right so that is another problem with your Setter injection so these two are disadvantages of your seter injection right now let's see Constructor injection next so Constructor injection is very important and it's mostly use inside IT industry most of the people use Constructor injection right because it brings lot of advantages right and it overcomes the disadvantages of your field injection and your seter injection right so both the the problems that we have seen with Setter and uh field injection will be overcomed by using Constructor injection right so very very important right as the name suggest dependency will be resolved at the time of initialization of your object now Constructor injection is while creation of your bean only the dependencies will be injected now let's see how right now let me remove this Setter right what I'll do here we have this right what I'll do I'll add order over here at this order what I will do here I will do this do order equal to order let me remove this code as well and now what I will do I will add Auto Wi on top of this so once I add Auto Wi on top of this this dependency will be injected by using Constructor right this is something which we called as Constructor injection right now let's say there are multiple Fields as well so multiple Fields also you can add inside your Constructor right all those fields will be initialized accordingly right and these beans will be injected so what will happen over here is when the application will be started your order will be created right so the order object will be created and it will be inside your ioc container right so when the user will be initialized it will check okay that we need to do Constructor initialization over here so when it will try to initialize your user object what it will do is it will try to find for this order it will check if this order is present inside our ioc container already so it will go ahead and see ISU container order we have already initialized what it will do it it will inject that same order here and that same order will be assigned to this order that we have over here right so that's how the dependency will be injected now if you rerun this code it should print the similar kind of results so initializing order and initializing user right so that is how the dependency is being injected basically and that is the Constructor injection for us as we have discussed it is recommended right and the advantages of that we will see now one more point to highlight here is when there is only one Constructor present and autowired is is not mandatory right so let's say there is only one Constructor even if I remove that and let's say rerun this code then this dependency will still be injected because spring will use reflection right and it will analyze that okay this order is also a component spring component we already have that component right we already have that bean present what it will do it will inject the same beIN directly okay but let's say there is some other class as well right for example let's say we have online order right and now we have other uh Constructor as well let's say we have two Constructors online order right so this Dot online order I will do right now we have two Constructor right now in this case the auto is mandatory because it will get confused that which Bean needs to be initialized well let's try to run this and let's see what happens see so we are getting errors basically Bean instantiation exception fail to instantiate Bean because it don't know which means to be uh instantiated basically so we can explicitly say that okay I want to inject this one so now if we run this code it should work fine right as you can see it is working fine now right now you may ask that okay initializing order is still printed on the console here that is printed because this order is still a spring component right so it will still create a bean you're using it or not using it it will still create a bean and will initialize this object and keep it in I container right that's why this statement is basically printing so what what we can do let's go ahead and print this as well so in online order so that again should be printed on the console let's see so there we go so that is also printed uh in order to check that let's debug let me add a debug point over here and let's see what happens now let me run the application in debug mode now so here as you can see online order is injected but order is still null over here right this is null because we are not injecting it we haven't added any auto or so over here right so that is the problem so that is the reason this order is not being injected and our guy online order is being injected right now let's try something now let's uh add autoed here as well now we have two Auto now let's say it is giving error only one Constructor can have autoed annotation right so you cannot have Auto wir on more than one Constructor now let's say if you want to initialize both of them at one go what we can do is we can remove this can have one more online order over here and what we can do this do online order equal to online order right now when we run this code it will inject both the dependencies right there we go now let's add a debug Point again and let's debug and check let me run it in debug mode and as you can see here now order and online order both the orders are injected properly right so that is how the Constructor injection basically works right if you only have one Constructor then Auto wired is not mandatory if you have more than one Constructor then you should have Auto wired on at least one Constructor right otherwise you will get the compile time failures right now let's discuss the advantages now here all mandatory dependencies will be injected at the time of initialization itself so as I mentioned when your application is coming up and your bean is being formed at that time only the in the dependencies will be injected right so these two dependencies will be injected while this Bean is being formed right it makes 100% sure that your object will be initialized with all your proper dependencies right otherwise it won't be initialized right this avoids any null pointer exceptions that we faced in field injection because no such cases will be there your object will never be null right so as we need to pass these two there will not be any scenario where order and online order is null next is we can create immutable objects using Constructor injection very very important right as we have seen here the disadvantages field cannot be marked as final you know inside seter injection and inside field as well we have the same disadvantage cannot be used with immutable Fields right but let's see here now here what I will do I will make this guy finally are we getting any error no we are not because it will work because this order we are initializing inside your Constructor right and while your bean will be injected and while this Bean is created this order which is coming from your ioc container will be assigned to this order that means this final will be assigned so immutable Fields also you can inject by using Constructor injection right so that is the advantage of your Constructor injection right that's why this Constructor injection is uh very useful and many peoples are using right that's why it is more important right and that is the reason why it is recommended as well right now fail fast now let's say any of the dependencies are missing then it will fail at compile time only it will say that there is no dependency then it will fail at that time only right so fail fast behavior of your Constructors right so that is another advantage of your Constructor injection for example for example let's say this online order is not a component let's say let me remove this component annotation from here and if I run this application now let's see what happens see it fails online order could not be found because there is no such be we have removed component so there is no point of finding the bean right so this is the fail fast behavior and it will give you the exact error why it is failing right that is fail fast behavior for us that will be helpful for us to understand that which beans are missing or which dependencies are missing basically right let me r that changes right now if we run this code it should uh come up fine right so let's see so it is coming up fine right so everything is fine over here so all those are advantages of your Constructor injection right so that is uh so that marks the end of our Constructor injection as well now let's disc the problem faced during dependency injection right so first problem is your circular dependencies right so what is circular dependencies let's try to visualize it over here now let's say you have order right so let's say this is order class and let's say you have user class right now till now what we are doing we are adding order inside your user right so we are Auto wiring your order inside your user so what we are going to do now is we are going to inject this user as as well inside your order so this is a circular dependency your order is dependent on user and user is dependent on order right so that marks the circular dependency right so let's see how so uh let me create such scenario now let me just remove this final and uh let me remove this as well we don't need it anymore I will remove that remove this as well what I will do I'll go to use order and what I will do I will create the object of user over here and there we go and what I will do I'll do I'll initialize it by using Constructor injection right and I will say this do user equals to user and what I will do I auto this right so this is Constructor injection basically now let's say now let's run this code and let's see what happens see it is giving error and it is saying the dependencies of some beans in your application form a cycle so it is exactly giving us the error saying that there is a cyclic dependency in your project go and fix it right and also it is giving us the classes that order has dependency on user user has dependency on order right now this cyclic dependency how we can resolve so one way to resolve the cyclic dependency is by using lazy annotation right so uh if you have seen the last video here so when the beans will get created right so eager initialization is the one and other is lazy initialization right this last video that I have asked you to go through through right uh which is kind of a dependency for this video right so lazy initialization is basically injecting beans whenever they are needed right so how we achieve this by using lazy annotation right so what we can do here is let's say order have dependency on user and user have dependency on order right so what we can do here is while creating object of user what you can do here at Constructor level you can add lazy as we are doing The Constructor injection over here so at that point you can add lazy right now if you run this code all your beans are getting created fine right so this is how you can use lazy annotation to avoid cyclic dependency and you can add it on a bean level as well or you can add it on you know Constructor level as well or you can add it on field level as well if you are doing field injection you can add it on seter level as well if you are doing seter injection right so that is how you can resolve by using lazy annotation right these cyc dependencies so there is one more way to resolve the cyclic dependencies that is by using your post construct what we will do here we will use field injection over here let's say and in order what we will do we'll remove this annotation right we won't use any auto wir over here and we need to remove this as because it will consider this as the Constructor injection right if you remember we don't need to give Auto wi in case of Constructor injection but this is a default Constructor so should be fine so here user we will remove everything and what we will do we will add one method let's say public void init let's say and here what we will do inside this we will say here Order set order right set order we need to do and what we need to set this object the object of your order right so this set order method we need to create inside your order and here what we need to do this do user we need to assign to this user right so this is how you can inject by using post construct one more thing we missed here here we need to annotate this with not lazy with post construct right after constructing this user being set this user being inside your order right so it will just call this it will just set this user here right so you don't need to use Auto wiring over here rather you can use this Setter and you can inject by using post construct so this is how you can uh manage the cyclic dependency by using post construct as well right so as you can see everything is initialized properly right so that is a um circular dependency for us so that we have addressed right now let's see unsatisfied dependency now we have seen one unsatisfied dependency already right when we had let's say object of online order as well right we had online order and here I will do comma and add online order and here I will add let's say this do online order equals to online order and I will annotate this with let's say autowired I will remove the auto wir from here I will remove remove this post construct now let's say this online order is not a component it is not a component itself so if you try to inject it obviously you are going to get some error that there is a dependency missing right so what happened what happened okay let me remove this as well let me rerun this so now if you can see uh this is giving that your dependency is missing right this online order is missing basically right so what what I will do I'll just uh bring this back and what we can do here let me refactor this code a bit right what I do I'll remove this order I will convert this order to a interface again right what we will do let's convert it to interface right let me remove this remove this as well we don't need anything we just need the empty interface and this online order Let's uh Implement by using that particular order let's create another order let's say it's offline order class right and this will also Implement order right so there are two classes implementing order now here also we let's say just add one uh Constructor we just add a Constructor over here and let's just print one statement let's say this particular is offline order and um now what we will do online order offline order this is a concrete thing so we shouldn't use it let's use order only right so now I'm just injecting order right but which order will be injected over here well let's see now if I run this code now see this is working fine because we haven't converted this offline order to a spring component so what I will do convert it to Spring component as well so that we have two beans of your order type right now let's run this code and let's see what happens now as you can see it is saying that that user required a single Bean but two found right it wanted only order but it found two type of order online and offline right so this is basically unsatisfied dependency issue right that it's not able to find the correct dependency right it's not able to find the right order to inject in that case what we can do is we can we can mark one of the component as primary that whenever this is used I want to inject this one now if we run this code let's see what happens now it is being injected fine right all the beans are being initialized and here when the user is created at the time of order it is injecting your online order in order to check that let's debug this code right now I'm running this code in debug mode and as you can see this order is basically online order over here right so that's how you can do it by using primary let's say you want to you know inject the offline one as well but what you need to do is you need to go ahead and Mark that one as primary but the second way to address this problem is let's remove it we can use something called as qualifier so as you can see here also it is throwing some error saying that could not Auto wire so the other approach we can do here is by using qualifier so what we can do we can add a qualifier that when we try to inject the order which order we want to inject let's say I want to inject online order I can just select that right so it is basically the name of your bean with camel case so first L will be small and the rest of the name will be same right like that we can inject over here and now if we run this code that particular online order will be injected right and uh if you debug this code then again you will see the online order being injected okay here if you can see online order is being injected now let's say we want to inject offline order what we can do we can just say offline order over here and let's rerun this code or let's debug this again so as you can see now the offline order is being injected right so that is the use of qualifier so just to reiterate uh if you have let's say one interface and it has multiple implementation and you are injecting that interface right as our dependency inversion of solid principle suggest we should use the abstraction at the time if there are multiple implementation and all of those are spring beans then your spring will be confused which one to inject at that time your qualifier comes into picture and it will say Okay I want this particular um Bean to be injected uh like that I want offline order and like that offline order will be injected in this case right so that is the issue that is the unsatisfied dependency issue and that is how you can address it right by using let's say primary or let's say by using qualifier as well right so that marks the end of it so basically we have covered everything so I hope that you have Fair understanding of dependency injection inside spring now and you can answer all the interview questions so thank you so much for watching the video If if you like the video hit the like button don't forget to subscribe to my channel and don't forget to share this video with your friends so that they can also learn dependency injection right and that's it see you in the next video