{"id":176,"date":"2023-04-06T19:48:31","date_gmt":"2023-04-06T19:48:31","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=176"},"modified":"2023-08-23T16:22:29","modified_gmt":"2023-08-23T16:22:29","slug":"java-serviceloader-implementing-customizing-spis","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/","title":{"rendered":"Java ServiceLoader: Implementing and Customizing Service Provider Interfaces (SPIs)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">You may have encountered situations where you need to extend or customize the functionality of a library or framework without modifying its original source code. Service Provider Interfaces (SPIs) are a powerful way to achieve this goal, allowing you to create modular and extensible applications. In this article, we&#8217;ll dive into the Java ServiceLoader, a key feature for implementing and customizing SPIs. By the end of this guide, you will understand how ServiceLoader works, how to implement and customize SPIs, and best practices for using this powerful tool.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Understanding Java ServiceLoader<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class at runtime. It uses the Java classpath to discover and load service provider classes, enabling developers to seamlessly extend applications without modifying existing code. ServiceLoader supports lazy loading, making it an efficient way to locate and instantiate service providers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Key Concepts in Implementing and Customizing SPIs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before diving into the implementation, let&#8217;s review some essential concepts related to SPIs:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Service Provider Interface (SPI)<\/strong>: An SPI is a well-defined interface or abstract class that developers implement to provide custom functionality. The SPI acts as a contract, ensuring that all implementations adhere to the same set of rules.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Service Provider<\/strong>: A service provider is a concrete implementation of an SPI. Service providers can be created by third-party developers, allowing them to extend the functionality of an application or library.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Service Configuration File<\/strong>: To use a service provider with the ServiceLoader, you must declare it in a service configuration file. This file is placed in the META-INF\/services directory and named after the fully-qualified name of the SPI.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Implementing a Service Provider Interface<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To implement a custom SPI, follow these steps:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">a. Define the SPI: Create an interface or abstract class that will act as the SPI. This contract will define the methods that service providers must implement.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">PaymentProcessor<\/span> <\/span>{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">processPayment<\/span><span class=\"hljs-params\">(Payment payment)<\/span><\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">b. Implement the Service Provider: Create a concrete class that implements the SPI. This class will provide the custom functionality for your application.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PayPalProcessor<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">PaymentProcessor<\/span> <\/span>{\n    <span class=\"hljs-meta\">@Override<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">processPayment<\/span><span class=\"hljs-params\">(Payment payment)<\/span> <\/span>{\n        <span class=\"hljs-comment\">\/\/ PayPal-specific payment processing logic<\/span>\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">c. Register the Service Provider: Create a service configuration file in the META-INF\/services directory. Name the file after the fully-qualified name of the SPI and include the fully-qualified name of your service provider class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">META-INF\/services\/com.example.PaymentProcessor:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">com.example.PayPalProcessor<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Customizing and Loading Service Providers with ServiceLoader<br>To load and use service providers with the ServiceLoader, follow these steps:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">a. Load Service Providers: Instantiate a ServiceLoader with the SPI&#8217;s class as a type parameter.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">ServiceLoader&lt;PaymentProcessor&gt; serviceLoader = ServiceLoader.load(PaymentProcessor<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">b. Iterate and Use Service Providers: Iterate over the available service providers and call their methods.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">for<\/span> (PaymentProcessor processor : serviceLoader) {\n    processor.processPayment(payment);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Best Practices for Implementing and Customizing SPIs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To get the most out of the Java ServiceLoader and SPIs, keep the following best practices in mind:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Keep the SPI minimal<\/strong>: Focus on the essential methods and functionality for your SPI to make it easier to implement and maintain.<\/li>\n\n\n\n<li><strong>Separate API and SPI<\/strong>: Keep the API and SPI separate to ensure a clear distinction between their roles. This separation will make it easier to maintain and evolve the SPI without affecting the API.<\/li>\n\n\n\n<li><strong>Design for extensibility<\/strong>: Ensure that your SPI design allows for future extensions and modifications without breaking existing implementations. Use default methods in interfaces, if necessary, to add new functionality without impacting existing providers.<\/li>\n\n\n\n<li><strong>Document your SPI<\/strong>: Provide clear and concise documentation for your SPI, explaining its purpose, usage, and any required behavior for service provider implementations. This documentation will help third-party developers understand and implement the SPI correctly.<\/li>\n\n\n\n<li><strong>Use versioning<\/strong>: When releasing a new version of your SPI, consider using semantic versioning to communicate breaking changes, new features, and bug fixes. This practice will help developers understand the impact of upgrading to a new version of your SPI.<\/li>\n\n\n\n<li><strong>Encapsulate service providers<\/strong>: Encapsulate the logic and data of service providers within their classes. This encapsulation ensures that the service provider&#8217;s internal state is not exposed, making it easier to maintain and evolve.<\/li>\n\n\n\n<li><strong>Provide a default implementation<\/strong>: When appropriate, provide a default implementation of your SPI. This default implementation can serve as a reference for other service providers and can be used by applications when no other suitable service providers are available.<\/li>\n\n\n\n<li><strong>Test your SPI and service providers<\/strong>: Thoroughly test your SPI and service providers to ensure they function correctly and adhere to the SPI&#8217;s contract. This testing will help catch issues early in the development process and improve the overall quality of your SPI and service providers.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Example Exercise<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this exercise, we will create a text formatting library that allows third-party developers to implement their custom formatters for different text styles. The library will use the Java ServiceLoader to discover and use these custom formatters at runtime.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">1. <strong>Define the SPI<\/strong>: Create a <strong><code>TextFormatter<\/code><\/strong> interface that defines the contract for custom text formatters.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">TextFormatter<\/span> <\/span>{\n    <span class=\"hljs-function\">String <span class=\"hljs-title\">format<\/span><span class=\"hljs-params\">(String text)<\/span><\/span>;\n    <span class=\"hljs-function\">String <span class=\"hljs-title\">getSupportedStyle<\/span><span class=\"hljs-params\">()<\/span><\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">2. <strong>Implement the default Service Provider<\/strong>: Create a default service provider that capitalizes the input text.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CapitalizeFormatter<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">TextFormatter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">format<\/span><span class=\"hljs-params\">(String text)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> text.toUpperCase();\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">getSupportedStyle<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"CAPITALIZE\"<\/span>;\r\n    }\r\n}\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">3. <strong>Register the default Service Provider<\/strong>: Create a service configuration file in the META-INF\/services directory. Name the file after the fully-qualified name of the SPI and include the fully-qualified name of your service provider class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">META-INF\/services\/com.example.TextFormatter:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">com.example.CapitalizeFormatter\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">4. <strong>Create a utility class to apply formatting<\/strong>: The utility class will use the <strong><code>ServiceLoader<\/code><\/strong> to discover and apply the appropriate formatter based on the provided style.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> java.util.HashMap;\r\n<span class=\"hljs-keyword\">import<\/span> java.util.Map;\r\n<span class=\"hljs-keyword\">import<\/span> java.util.ServiceLoader;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TextFormatUtil<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> Map&lt;String, TextFormatter&gt; formatters = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;();\r\n\r\n    <span class=\"hljs-keyword\">static<\/span> {\r\n        ServiceLoader&lt;TextFormatter&gt; serviceLoader = ServiceLoader.load(TextFormatter<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;\r\n        <span class=\"hljs-keyword\">for<\/span> (TextFormatter formatter : serviceLoader) {\r\n            formatters.put(formatter.getSupportedStyle(), formatter);\r\n        }\r\n    }\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> String <span class=\"hljs-title\">format<\/span><span class=\"hljs-params\">(String text, String style)<\/span> <\/span>{\r\n        TextFormatter formatter = formatters.get(style);\r\n        <span class=\"hljs-keyword\">if<\/span> (formatter == <span class=\"hljs-keyword\">null<\/span>) {\r\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException(<span class=\"hljs-string\">\"Unsupported style: \"<\/span> + style);\r\n        }\r\n        <span class=\"hljs-keyword\">return<\/span> formatter.format(text);\r\n    }\r\n}\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">5. <strong>Third-party developer creates a custom formatter<\/strong>: A third-party developer implements a <strong><code>TextFormatter<\/code><\/strong> for leetspeak style.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LeetSpeakFormatter<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">TextFormatter<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">format<\/span><span class=\"hljs-params\">(String text)<\/span> <\/span>{\r\n        <span class=\"hljs-comment\">\/\/ Leetspeak formatting logic<\/span>\r\n        <span class=\"hljs-keyword\">return<\/span> text.replaceAll(<span class=\"hljs-string\">\"a\"<\/span>, <span class=\"hljs-string\">\"4\"<\/span>)\r\n                   .replaceAll(<span class=\"hljs-string\">\"e\"<\/span>, <span class=\"hljs-string\">\"3\"<\/span>)\r\n                   .replaceAll(<span class=\"hljs-string\">\"l\"<\/span>, <span class=\"hljs-string\">\"1\"<\/span>)\r\n                   .replaceAll(<span class=\"hljs-string\">\"o\"<\/span>, <span class=\"hljs-string\">\"0\"<\/span>)\r\n                   .replaceAll(<span class=\"hljs-string\">\"t\"<\/span>, <span class=\"hljs-string\">\"7\"<\/span>);\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">getSupportedStyle<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"LEETSPEAK\"<\/span>;\r\n    }\r\n}\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">6. <strong>Third-party developer registers their custom formatter<\/strong>: The third-party developer creates a service configuration file in their project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">META-INF\/services\/com.example.TextFormatter:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">com.example.LeetSpeakFormatter\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">7. <strong>Usage example<\/strong>: An application uses the <strong><code>TextFormatUtil<\/code><\/strong> to format text with different styles.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Main<\/span> <\/span>{\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        String text = <span class=\"hljs-string\">\"hello world\"<\/span>;\r\n\r\n        String capitalized = TextFormatUtil.format(text, <span class=\"hljs-string\">\"CAPITALIZE\"<\/span>);\r\n        System.out.println(capitalized); <span class=\"hljs-comment\">\/\/ Output: HELLO WORLD<\/span>\r\n\r\n        String leetspeak = TextFormatUtil.format(text, <span class=\"hljs-string\">\"LEETSPEAK\"<\/span>);\r\n        System.out.println(leetspeak); <span class=\"hljs-comment\">\/\/ Output: H3110 W0R1D<\/span>\r\n    }\r\n}\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">In this exercise, we created an extensible text formatting library using the Java ServiceLoader and SPIs. The library allows third-party developers to implement custom formatters, which can be discovered and used at runtime. By following the best practices outlined earlier, this library can be easily maintained and extended with new formatting styles as needed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You may have encountered situations where you need to extend or customize the functionality of a library or framework without modifying its original source code. Service Provider Interfaces (SPIs) are a powerful way to achieve this goal, allowing you to create modular and extensible applications. In this article, we&#8217;ll dive into the Java ServiceLoader, a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[5,4],"tags":[],"class_list":["post-176","post","type-post","status-publish","format-standard","category-java","category-programming-languages","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java ServiceLoader: Implementing and Customizing SPIs<\/title>\n<meta name=\"description\" content=\"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java ServiceLoader: Implementing and Customizing SPIs\" \/>\n<meta property=\"og:description\" content=\"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-04-06T19:48:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-23T16:22:29+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"Java ServiceLoader: Implementing and Customizing Service Provider Interfaces (SPIs)\",\"datePublished\":\"2023-04-06T19:48:31+00:00\",\"dateModified\":\"2023-08-23T16:22:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/\"},\"wordCount\":988,\"commentCount\":0,\"articleSection\":[\"Java\",\"Programming Languages\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/\",\"name\":\"Java ServiceLoader: Implementing and Customizing SPIs\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2023-04-06T19:48:31+00:00\",\"dateModified\":\"2023-08-23T16:22:29+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"description\":\"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-serviceloader-implementing-customizing-spis\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming Languages\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Java ServiceLoader: Implementing and Customizing Service Provider Interfaces (SPIs)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java ServiceLoader: Implementing and Customizing SPIs","description":"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/","og_locale":"en_US","og_type":"article","og_title":"Java ServiceLoader: Implementing and Customizing SPIs","og_description":"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class","og_url":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/","article_published_time":"2023-04-06T19:48:31+00:00","article_modified_time":"2023-08-23T16:22:29+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"Java ServiceLoader: Implementing and Customizing Service Provider Interfaces (SPIs)","datePublished":"2023-04-06T19:48:31+00:00","dateModified":"2023-08-23T16:22:29+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/"},"wordCount":988,"commentCount":0,"articleSection":["Java","Programming Languages"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/","url":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/","name":"Java ServiceLoader: Implementing and Customizing SPIs","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2023-04-06T19:48:31+00:00","dateModified":"2023-08-23T16:22:29+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"description":"The Java ServiceLoader, introduced in Java 6, is a core utility that locates and loads implementations of a given interface or abstract class","breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/java-serviceloader-implementing-customizing-spis\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Programming Languages","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/"},{"@type":"ListItem","position":3,"name":"Java ServiceLoader: Implementing and Customizing Service Provider Interfaces (SPIs)"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=176"}],"version-history":[{"count":3,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/176\/revisions"}],"predecessor-version":[{"id":197,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/176\/revisions\/197"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}