In most of the applications we are using Dependency Injection
for loosely couple of our code. Some time, we just require simple DI, nothing else, for those, we need to include some of our DI frameworks like Spring
, Google Guice
etc. This makes our project jar heavy and added some unnecessary classes as well. For all these, Java itself have a ServiceLoader
class for inject your dependency at run time. ServiceLoader
had introduce in JDK 3, but this is used for internal purpose. During JDK 6
, this class scopes to public but still, it is a final class, we are not able to extends its functionality.
ServiceLoader
will play important role in JDK 9, Which we will discuss in our next post. Today, we are creating a simple Greetings application using ServiceLoader
as below:
Step I: Prerequisite
- JDK >= 6
- Maven
Step II:
Creating an abstract layer for any service, which implementation decide and runtime like below code:
package com.knoldus.service; public interface GreetingsService { void sayHello(String name); }
Creating an implementation of service by implementing interface as below:
package com.knoldus.service.impl; import com.knoldus.service.GreetingsService; public class ConsoleGreetings implements GreetingsService { @Override public void sayHello(String name) { System.out.println("Hello to "+name); } }
Step III:
Now we need to define our provider, which loads GreetingsService
implementations at run time and create and instance to it.
import java.util.ServiceLoader; public class GreetingsProvider { private static GreetingsProvider provider; private ServiceLoader<GreetingsService> loader; private GreetingsProvider() { loader = ServiceLoader.load(GreetingsService.class); } public static GreetingsProvider getInstance() { if(provider == null) { provider = new GreetingsProvider(); } return provider; } public GreetingsService serviceImpl() { GreetingsService service = loader.iterator() .next(); if(service != null){ return service; }else { throw new NoSuchElementException("No implementation for GreetingsProvider"); } } }
Note: For loading GreetingService
we are using ServiceLoader
, If GreetingsService
have multiple implementation, the ServiceLoader
will load all of its implementation, this depends on us, how we can handle implementations. In above code, i am assuming only one implementation and find out using next().
Step IV:
Creating a directory META-INF/service
on your classpath. That directory contains a file with full qualified name of your abstract service class like
com.knoldus.service.GreetingsService
This files contains the details of its implementation as below:
com.knoldus.service.impl.ConsoleGreetings
Step V:
Create a main class for code execution as below:
package com.knoldus.main; import com.knoldus.providers.GreetingsProvider; import com.knoldus.service.GreetingsService; public class Launcher { public static void main(String... args) { GreetingsService service = GreetingsProvider.getInstance().serviceImpl(); service.sayHello("Knoldus"); } }
For more information about ServiceLoader
click on this link.
For downloading source code click on this link.
Great….!!!! Very usefull
Interesting idea using ServiceLoader for DI but… e.g. how do you inject your GreetingsService instance for e.g. another service? How it’s possible to create application objects tree in this way?
Reblogged this on Harmeet Singh(Taara).