Play With Java ServiceLoader forget about Dependency Injection(DI) Frameworks

Reading Time: 2 minutes

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(&quot;No implementation for GreetingsProvider&quot;);
        }
    }
}

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(&quot;Knoldus&quot;);
    }
}

For more information about ServiceLoader click on this link.

For downloading source code click on this link.

References:


KNOLDUS-advt-sticker

Written by 

Harmeet Singh is a lead consultant, with experience of more than 5 years. He has expertise in Scala, Java, JVM, and functional programming. On a personal front; he is a food lover.

4 thoughts on “Play With Java ServiceLoader forget about Dependency Injection(DI) Frameworks2 min read

  1. 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?

Comments are closed.