This is an automated email from the ASF dual-hosted git repository.

jianglongtao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob.git


The following commit(s) were added to refs/heads/master by this push:
     new b781c7620 Reuse ShardingSphereServiceLoader to instead of 
ElasticJobServiceLoader (#2308)
b781c7620 is described below

commit b781c7620097bef62cdb4c7b181c881228200b22
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Oct 24 07:53:28 2023 +0800

    Reuse ShardingSphereServiceLoader to instead of ElasticJobServiceLoader 
(#2308)
    
    * Remove JobErrorHandlerFactory
    
    * Remove JobErrorHandlerFactory
    
    * Remove JobErrorHandlerFactory
    
    * Remove JobErrorHandlerFactory
    
    * Remove JobErrorHandlerFactory
    
    * Refactor SPI for Reloadable
    
    * Refactor SPI for Reloadable
    
    * Refactor SPI for TypedJobItemExecutor
    
    * Refactor SPI for JobErrorHandlerPropertiesValidator
    
    * Refactor SPI for ElasticJobListener
    
    * Refactor SPI for JobShardingStrategy
    
    * Refactor SPI for JobExecutorServiceHandler
    
    * Refactor SPI for JobExecutorServiceHandler
    
    * Remove ElasticJobServiceLoader
    
    * Remove ElasticJobServiceLoader
    
    * Fix checkstyle
    
    * Fix spotless
---
 .../elasticjob/error/handler/JobErrorHandler.java  |  8 +-
 .../JobErrorHandlerPropertiesValidator.java        | 15 +++-
 ...talkJobErrorHandlerPropertiesValidatorTest.java | 27 ++----
 .../dingtalk/DingtalkJobErrorHandlerTest.java      |  6 +-
 ...mailJobErrorHandlerPropertiesValidatorTest.java | 27 ++----
 .../handler/email/EmailJobErrorHandlerTest.java    |  6 +-
 .../error/handler/JobErrorHandlerFactory.java      | 53 ------------
 .../error/handler/JobErrorHandlerReloadable.java   | 27 ++----
 .../handler/general/IgnoreJobErrorHandler.java     |  6 --
 .../error/handler/general/LogJobErrorHandler.java  | 11 ++-
 .../handler/general/ThrowJobErrorHandler.java      |  6 --
 .../error/handler/JobErrorHandlerFactoryTest.java  | 47 -----------
 .../handler/JobErrorHandlerReloadableTest.java     | 70 ++++++++--------
 .../handler/general/IgnoreJobErrorHandlerTest.java |  7 +-
 .../handler/general/LogJobErrorHandlerTest.java    |  6 +-
 .../handler/general/ThrowJobErrorHandlerTest.java  |  7 +-
 ...chatJobErrorHandlerPropertiesValidatorTest.java | 27 ++----
 .../handler/wechat/WechatJobErrorHandlerTest.java  |  6 +-
 .../elasticjob/executor/ElasticJobExecutor.java    |  4 +-
 .../executor/context/ExecutorContext.java          | 33 ++------
 .../executor/item/JobItemExecutorFactory.java      | 16 +---
 .../executor/item/impl/TypedJobItemExecutor.java   |  4 +-
 .../executor/item/JobItemExecutorFactoryTest.java  | 11 ---
 infra/pom.xml                                      |  5 ++
 .../concurrent/ExecutorServiceReloadable.java      | 32 +++----
 .../elasticjob/infra/context/Reloadable.java       | 18 +++-
 .../infra/context/ReloadablePostProcessor.java     | 33 --------
 .../handler/sharding/JobShardingStrategy.java      |  2 +-
 .../sharding/JobShardingStrategyFactory.java       | 51 ------------
 .../impl/AverageAllocationJobShardingStrategy.java |  7 +-
 .../threadpool/JobExecutorServiceHandler.java      |  4 +-
 .../JobExecutorServiceHandlerFactory.java          | 51 ------------
 .../impl/CPUUsageJobExecutorServiceHandler.java    |  5 ++
 .../infra/listener/ElasticJobListener.java         |  2 +-
 .../infra/listener/ElasticJobListenerFactory.java  |  9 +-
 .../infra/spi/ElasticJobServiceLoader.java         | 97 ----------------------
 .../elasticjob/infra/spi/SPIPostProcessor.java     | 33 --------
 .../elasticjob/infra/spi/TypedSPI.java             | 31 -------
 .../ServiceLoaderInstantiationException.java       | 30 -------
 .../infra/validator/JobPropertiesValidator.java    | 35 --------
 .../concurrent/ExecutorServiceReloadableTest.java  | 45 +++++-----
 .../sharding/JobShardingStrategyFactoryTest.java   | 45 ----------
 .../JobExecutorServiceHandlerFactoryTest.java      | 45 ----------
 .../CPUUsageJobExecutorServiceHandlerTest.java     |  7 +-
 .../SingleThreadJobExecutorServiceHandlerTest.java |  7 +-
 .../listener/ElasticJobListenerFactoryTest.java    | 39 ---------
 .../listener/fixture/FooElasticJobListener.java    | 37 ---------
 .../infra/spi/ElasticJobServiceLoaderTest.java     | 71 ----------------
 .../infra/spi/fixture/TypedFooService.java         | 23 -----
 .../spi/fixture/UnRegisteredTypedFooService.java   | 23 -----
 .../spi/fixture/impl/TypedFooServiceImpl.java      | 28 -------
 .../impl/UnRegisteredTypedFooServiceImpl.java      | 28 -------
 ...re.elasticjob.infra.spi.fixture.TypedFooService | 18 ----
 ...b.infra.spi.fixture.UnRegisteredTypedFooService | 18 ----
 .../kernel/internal/schedule/JobScheduler.java     | 13 +--
 .../kernel/internal/sharding/ShardingService.java  |  4 +-
 pom.xml                                            |  6 ++
 .../job/parser/JobBeanDefinitionParser.java        | 15 ++--
 58 files changed, 223 insertions(+), 1124 deletions(-)

diff --git 
a/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandler.java
 
b/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandler.java
index 1b9f67fb3..868621306 100644
--- 
a/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandler.java
+++ 
b/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandler.java
@@ -17,15 +17,14 @@
 
 package org.apache.shardingsphere.elasticjob.error.handler;
 
-import org.apache.shardingsphere.elasticjob.infra.spi.SPIPostProcessor;
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 import java.io.Closeable;
 
 /**
  * Job error handler.
  */
-public interface JobErrorHandler extends TypedSPI, SPIPostProcessor, Closeable 
{
+public interface JobErrorHandler extends TypedSPI, Closeable {
     
     /**
      * Handle exception.
@@ -35,6 +34,9 @@ public interface JobErrorHandler extends TypedSPI, 
SPIPostProcessor, Closeable {
      */
     void handleException(String jobName, Throwable cause);
     
+    @Override
+    String getType();
+    
     @Override
     default void close() {
     }
diff --git 
a/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerPropertiesValidator.java
 
b/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerPropertiesValidator.java
index bcc26b266..d668554e0 100644
--- 
a/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerPropertiesValidator.java
+++ 
b/ecosystem/error-handler/spi/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerPropertiesValidator.java
@@ -17,10 +17,21 @@
 
 package org.apache.shardingsphere.elasticjob.error.handler;
 
-import 
org.apache.shardingsphere.elasticjob.infra.validator.JobPropertiesValidator;
+import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
+
+import java.util.Properties;
 
 /**
  * Job error handler properties validator.
  */
-public interface JobErrorHandlerPropertiesValidator extends 
JobPropertiesValidator {
+@SingletonSPI
+public interface JobErrorHandlerPropertiesValidator extends TypedSPI {
+    
+    /**
+     * Validate job properties.
+     *
+     * @param props job properties
+     */
+    void validate(Properties props);
 }
diff --git 
a/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerPropertiesValidatorTest.java
 
b/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerPropertiesValidatorTest.java
index 7cac93132..4ee20ef25 100644
--- 
a/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerPropertiesValidatorTest.java
+++ 
b/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerPropertiesValidatorTest.java
@@ -18,8 +18,7 @@
 package org.apache.shardingsphere.elasticjob.error.handler.dingtalk;
 
 import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerPropertiesValidator;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import java.util.Properties;
@@ -30,40 +29,26 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 class DingtalkJobErrorHandlerPropertiesValidatorTest {
     
-    @BeforeEach
-    void startup() {
-        
ElasticJobServiceLoader.registerTypedService(JobErrorHandlerPropertiesValidator.class);
-    }
-    
     @Test
     void assertValidateWithNormal() {
         Properties properties = new Properties();
         properties.setProperty(DingtalkPropertiesConstants.WEBHOOK, "webhook");
         
properties.setProperty(DingtalkPropertiesConstants.READ_TIMEOUT_MILLISECONDS, 
"1000");
         
properties.setProperty(DingtalkPropertiesConstants.CONNECT_TIMEOUT_MILLISECONDS,
 "2000");
-        DingtalkJobErrorHandlerPropertiesValidator actual = getValidator();
-        actual.validate(properties);
+        TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"DINGTALK").validate(properties);
     }
     
     @Test
     void assertValidateWithPropsIsNull() {
-        assertThrows(NullPointerException.class, () -> {
-            DingtalkJobErrorHandlerPropertiesValidator actual = getValidator();
-            actual.validate(null);
-        });
+        assertThrows(NullPointerException.class, () -> 
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"DINGTALK").validate(null));
     }
     
     @Test
     void assertValidateWithWebhookIsNull() {
-        DingtalkJobErrorHandlerPropertiesValidator actual = getValidator();
         try {
-            actual.validate(new Properties());
-        } catch (NullPointerException e) {
-            assertThat(e.getMessage(), is(String.format("The property `%s` is 
required.", DingtalkPropertiesConstants.WEBHOOK)));
+            
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"DINGTALK").validate(new Properties());
+        } catch (final NullPointerException ex) {
+            assertThat(ex.getMessage(), is(String.format("The property `%s` is 
required.", DingtalkPropertiesConstants.WEBHOOK)));
         }
     }
-    
-    private DingtalkJobErrorHandlerPropertiesValidator getValidator() {
-        return (DingtalkJobErrorHandlerPropertiesValidator) 
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandlerPropertiesValidator.class,
 "DINGTALK", null).get();
-    }
 }
diff --git 
a/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerTest.java
index cf971e3a7..c8d9aa744 100644
--- 
a/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/dingtalk/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/dingtalk/DingtalkJobErrorHandlerTest.java
@@ -20,12 +20,12 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.dingtalk;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import 
org.apache.shardingsphere.elasticjob.error.handler.dingtalk.fixture.DingtalkInternalController;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
 import org.apache.shardingsphere.elasticjob.restful.NettyRestfulService;
 import 
org.apache.shardingsphere.elasticjob.restful.NettyRestfulServiceConfiguration;
 import org.apache.shardingsphere.elasticjob.restful.RestfulService;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
@@ -124,7 +124,7 @@ class DingtalkJobErrorHandlerTest {
     }
     
     private DingtalkJobErrorHandler getDingtalkJobErrorHandler(final 
Properties props) {
-        return (DingtalkJobErrorHandler) 
JobErrorHandlerFactory.createHandler("DINGTALK", props).orElseThrow(() -> new 
JobConfigurationException("DINGTALK error handler not found."));
+        return (DingtalkJobErrorHandler) 
TypedSPILoader.getService(JobErrorHandler.class, "DINGTALK", props);
     }
     
     private Properties createConfigurationProperties(final String webhook) {
diff --git 
a/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerPropertiesValidatorTest.java
 
b/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerPropertiesValidatorTest.java
index 8fd94190f..b4d614b9d 100644
--- 
a/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerPropertiesValidatorTest.java
+++ 
b/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerPropertiesValidatorTest.java
@@ -18,8 +18,7 @@
 package org.apache.shardingsphere.elasticjob.error.handler.email;
 
 import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerPropertiesValidator;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import java.util.Properties;
@@ -30,11 +29,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 class EmailJobErrorHandlerPropertiesValidatorTest {
     
-    @BeforeEach
-    void startup() {
-        
ElasticJobServiceLoader.registerTypedService(JobErrorHandlerPropertiesValidator.class);
-    }
-    
     @Test
     void assertValidateWithNormal() {
         Properties properties = new Properties();
@@ -45,29 +39,20 @@ class EmailJobErrorHandlerPropertiesValidatorTest {
         properties.setProperty(EmailPropertiesConstants.PASSWORD, "password");
         properties.setProperty(EmailPropertiesConstants.FROM, "[email protected]");
         properties.setProperty(EmailPropertiesConstants.TO, "[email protected]");
-        EmailJobErrorHandlerPropertiesValidator actual = getValidator();
-        actual.validate(properties);
+        TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"EMAIL").validate(properties);
     }
     
     @Test
     void assertValidateWithPropsIsNull() {
-        assertThrows(NullPointerException.class, () -> {
-            EmailJobErrorHandlerPropertiesValidator actual = getValidator();
-            actual.validate(null);
-        });
+        assertThrows(NullPointerException.class, () -> 
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"EMAIL").validate(null));
     }
     
     @Test
     void assertValidateWithHostIsNull() {
-        EmailJobErrorHandlerPropertiesValidator actual = getValidator();
         try {
-            actual.validate(new Properties());
-        } catch (NullPointerException e) {
-            assertThat(e.getMessage(), is(String.format("The property `%s` is 
required.", EmailPropertiesConstants.HOST)));
+            
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"EMAIL").validate(new Properties());
+        } catch (final NullPointerException ex) {
+            assertThat(ex.getMessage(), is(String.format("The property `%s` is 
required.", EmailPropertiesConstants.HOST)));
         }
     }
-    
-    private EmailJobErrorHandlerPropertiesValidator getValidator() {
-        return (EmailJobErrorHandlerPropertiesValidator) 
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandlerPropertiesValidator.class,
 "EMAIL", null).get();
-    }
 }
diff --git 
a/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerTest.java
index 169f02287..78a1cf359 100644
--- 
a/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/email/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/email/EmailJobErrorHandlerTest.java
@@ -21,8 +21,8 @@ import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import lombok.SneakyThrows;
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -97,7 +97,7 @@ class EmailJobErrorHandlerTest {
     }
     
     private EmailJobErrorHandler getEmailJobErrorHandler(final Properties 
props) {
-        return (EmailJobErrorHandler) 
JobErrorHandlerFactory.createHandler("EMAIL", props).orElseThrow(() -> new 
JobConfigurationException("EMAIL error handler not found."));
+        return (EmailJobErrorHandler) 
TypedSPILoader.getService(JobErrorHandler.class, "EMAIL", props);
     }
     
     private void setUpMockSession(final Session session) {
diff --git 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactory.java
 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactory.java
deleted file mode 100644
index 5e77909bc..000000000
--- 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactory.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.error.handler;
-
-import com.google.common.base.Strings;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-
-import java.util.Optional;
-import java.util.Properties;
-
-/**
- * Job error handler factory.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class JobErrorHandlerFactory {
-    
-    public static final String DEFAULT_HANDLER = "LOG";
-    
-    static {
-        ElasticJobServiceLoader.registerTypedService(JobErrorHandler.class);
-    }
-    
-    /**
-     * Get job error handler.
-     *
-     * @param type job error handler type
-     * @param props job properties
-     * @return job error handler
-     */
-    public static Optional<JobErrorHandler> createHandler(final String type, 
final Properties props) {
-        if (Strings.isNullOrEmpty(type)) {
-            return 
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandler.class, 
DEFAULT_HANDLER, props);
-        }
-        return 
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandler.class, type, 
props);
-    }
-}
diff --git 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadable.java
 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadable.java
index 125656103..f81bfc91b 100644
--- 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadable.java
+++ 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadable.java
@@ -17,12 +17,10 @@
 
 package org.apache.shardingsphere.elasticjob.error.handler;
 
-import com.google.common.base.Strings;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.infra.context.Reloadable;
-import 
org.apache.shardingsphere.elasticjob.infra.context.ReloadablePostProcessor;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.util.Optional;
 import java.util.Properties;
@@ -31,9 +29,7 @@ import java.util.Properties;
  * JobErrorHandler reloadable.
  */
 @Slf4j
-public final class JobErrorHandlerReloadable implements 
Reloadable<JobErrorHandler>, ReloadablePostProcessor {
-    
-    private String jobErrorHandlerType;
+public final class JobErrorHandlerReloadable implements 
Reloadable<JobErrorHandler> {
     
     private Properties props;
     
@@ -41,28 +37,23 @@ public final class JobErrorHandlerReloadable implements 
Reloadable<JobErrorHandl
     
     @Override
     public void init(final JobConfiguration jobConfig) {
-        jobErrorHandlerType = 
Strings.isNullOrEmpty(jobConfig.getJobErrorHandlerType()) ? 
JobErrorHandlerFactory.DEFAULT_HANDLER : jobConfig.getJobErrorHandlerType();
         props = (Properties) jobConfig.getProps().clone();
-        jobErrorHandler = 
JobErrorHandlerFactory.createHandler(jobErrorHandlerType, props)
-                .orElseThrow(() -> new JobConfigurationException("Cannot find 
job error handler type '%s'.", jobErrorHandlerType));
+        jobErrorHandler = TypedSPILoader.getService(JobErrorHandler.class, 
jobConfig.getJobErrorHandlerType(), props);
     }
     
     @Override
     public synchronized void reloadIfNecessary(final JobConfiguration 
jobConfig) {
-        String newJobErrorHandlerType = 
Strings.isNullOrEmpty(jobConfig.getJobErrorHandlerType()) ? 
JobErrorHandlerFactory.DEFAULT_HANDLER : jobConfig.getJobErrorHandlerType();
-        if (newJobErrorHandlerType.equals(jobErrorHandlerType) && 
props.equals(jobConfig.getProps())) {
+        if 
(jobErrorHandler.getType().equals(jobConfig.getJobErrorHandlerType()) && 
props.equals(jobConfig.getProps())) {
             return;
         }
-        log.debug("JobErrorHandler reload occurred in the job '{}'. Change 
from '{}' to '{}'.", jobConfig.getJobName(), jobErrorHandlerType, 
newJobErrorHandlerType);
-        reload(newJobErrorHandlerType, jobConfig.getProps());
+        log.debug("JobErrorHandler reload occurred in the job '{}'. Change 
from '{}' to '{}'.", jobConfig.getJobName(), jobErrorHandler.getType(), 
jobConfig.getJobErrorHandlerType());
+        reload(jobConfig.getJobErrorHandlerType(), jobConfig.getProps());
     }
     
     private void reload(final String jobErrorHandlerType, final Properties 
props) {
         jobErrorHandler.close();
-        this.jobErrorHandlerType = jobErrorHandlerType;
         this.props = (Properties) props.clone();
-        jobErrorHandler = 
JobErrorHandlerFactory.createHandler(jobErrorHandlerType, props)
-                .orElseThrow(() -> new JobConfigurationException("Cannot find 
job error handler type '%s'.", jobErrorHandlerType));
+        jobErrorHandler = TypedSPILoader.getService(JobErrorHandler.class, 
jobErrorHandlerType, props);
     }
     
     @Override
@@ -71,8 +62,8 @@ public final class JobErrorHandlerReloadable implements 
Reloadable<JobErrorHandl
     }
     
     @Override
-    public String getType() {
-        return JobErrorHandler.class.getName();
+    public Class<JobErrorHandler> getType() {
+        return JobErrorHandler.class;
     }
     
     @Override
diff --git 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandler.java
 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandler.java
index 5eaab152d..5a7978e21 100644
--- 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandler.java
+++ 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandler.java
@@ -19,17 +19,11 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.general;
 
 import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 
-import java.util.Properties;
-
 /**
  * Job error handler for ignore exception.
  */
 public final class IgnoreJobErrorHandler implements JobErrorHandler {
     
-    @Override
-    public void init(final Properties props) {
-    }
-    
     @Override
     public void handleException(final String jobName, final Throwable cause) {
     }
diff --git 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandler.java
 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandler.java
index 2d98f0f45..75723b710 100644
--- 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandler.java
+++ 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandler.java
@@ -20,18 +20,12 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.general;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 
-import java.util.Properties;
-
 /**
  * Job error handler for log error message.
  */
 @Slf4j
 public final class LogJobErrorHandler implements JobErrorHandler {
     
-    @Override
-    public void init(final Properties props) {
-    }
-    
     @Override
     public void handleException(final String jobName, final Throwable cause) {
         log.error(String.format("Job '%s' exception occur in job processing", 
jobName), cause);
@@ -41,4 +35,9 @@ public final class LogJobErrorHandler implements 
JobErrorHandler {
     public String getType() {
         return "LOG";
     }
+    
+    @Override
+    public boolean isDefault() {
+        return true;
+    }
 }
diff --git 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandler.java
 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandler.java
index ffa329940..8883e8e5f 100644
--- 
a/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandler.java
+++ 
b/ecosystem/error-handler/type/general/src/main/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandler.java
@@ -20,17 +20,11 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.general;
 import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
 
-import java.util.Properties;
-
 /**
  * Job error handler for throw exception.
  */
 public final class ThrowJobErrorHandler implements JobErrorHandler {
     
-    @Override
-    public void init(final Properties props) {
-    }
-    
     @Override
     public void handleException(final String jobName, final Throwable cause) {
         throw new JobSystemException(cause);
diff --git 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactoryTest.java
 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactoryTest.java
deleted file mode 100644
index d715f9dc9..000000000
--- 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerFactoryTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.error.handler;
-
-import 
org.apache.shardingsphere.elasticjob.error.handler.general.LogJobErrorHandler;
-import 
org.apache.shardingsphere.elasticjob.error.handler.general.ThrowJobErrorHandler;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import org.junit.jupiter.api.Test;
-
-import java.util.Properties;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-class JobErrorHandlerFactoryTest {
-    
-    @Test
-    void assertGetDefaultHandler() {
-        assertThat(JobErrorHandlerFactory.createHandler("", new 
Properties()).orElse(null), instanceOf(LogJobErrorHandler.class));
-    }
-    
-    @Test
-    void assertGetInvalidHandler() {
-        assertThrows(JobConfigurationException.class, () -> 
JobErrorHandlerFactory.createHandler("INVALID", new 
Properties()).orElseThrow(() -> new JobConfigurationException("")));
-    }
-    
-    @Test
-    void assertGetHandler() {
-        assertThat(JobErrorHandlerFactory.createHandler("THROW", new 
Properties()).orElse(null), instanceOf(ThrowJobErrorHandler.class));
-    }
-}
diff --git 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadableTest.java
 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadableTest.java
index c574986ba..61973a949 100644
--- 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadableTest.java
+++ 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/JobErrorHandlerReloadableTest.java
@@ -29,66 +29,68 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import java.lang.reflect.Field;
 import java.util.Properties;
 
-import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 class JobErrorHandlerReloadableTest {
     
     @Mock
-    private JobErrorHandler mockJobErrorHandler;
+    private JobErrorHandler jobErrorHandler;
     
     @Test
     void assertInitialize() {
-        JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable();
-        String jobErrorHandlerType = "IGNORE";
-        JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType(jobErrorHandlerType).build();
-        assertNull(jobErrorHandlerReloadable.getInstance());
-        jobErrorHandlerReloadable.init(jobConfig);
-        JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
-        assertNotNull(actual);
-        assertThat(actual.getType(), equalTo(jobErrorHandlerType));
-        assertTrue(actual instanceof IgnoreJobErrorHandler);
+        try (JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable()) {
+            JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType("IGNORE").build();
+            assertNull(jobErrorHandlerReloadable.getInstance());
+            jobErrorHandlerReloadable.init(jobConfig);
+            JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
+            assertNotNull(actual);
+            assertThat(actual.getType(), is("IGNORE"));
+            assertTrue(actual instanceof IgnoreJobErrorHandler);
+        }
     }
     
     @Test
     void assertReload() {
-        JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable();
-        setField(jobErrorHandlerReloadable, "jobErrorHandler", 
mockJobErrorHandler);
-        setField(jobErrorHandlerReloadable, "jobErrorHandlerType", "mock");
-        setField(jobErrorHandlerReloadable, "props", new Properties());
-        String newJobErrorHandlerType = "LOG";
-        JobConfiguration newJobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType(newJobErrorHandlerType).build();
-        jobErrorHandlerReloadable.reloadIfNecessary(newJobConfig);
-        verify(mockJobErrorHandler).close();
-        JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
-        assertThat(actual.getType(), equalTo(newJobErrorHandlerType));
-        assertTrue(actual instanceof LogJobErrorHandler);
+        try (JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable()) {
+            when(jobErrorHandler.getType()).thenReturn("mock");
+            setField(jobErrorHandlerReloadable, "jobErrorHandler", 
jobErrorHandler);
+            setField(jobErrorHandlerReloadable, "props", new Properties());
+            String newJobErrorHandlerType = "LOG";
+            JobConfiguration newJobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType(newJobErrorHandlerType).build();
+            jobErrorHandlerReloadable.reloadIfNecessary(newJobConfig);
+            verify(jobErrorHandler).close();
+            JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
+            assertThat(actual.getType(), is(newJobErrorHandlerType));
+            assertTrue(actual instanceof LogJobErrorHandler);
+        }
     }
     
     @Test
     void assertUnnecessaryToReload() {
-        JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable();
-        String jobErrorHandlerType = "IGNORE";
-        JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType(jobErrorHandlerType).build();
-        jobErrorHandlerReloadable.init(jobConfig);
-        JobErrorHandler expected = jobErrorHandlerReloadable.getInstance();
-        jobErrorHandlerReloadable.reloadIfNecessary(jobConfig);
-        JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
-        assertThat(actual, is(expected));
+        try (JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable()) {
+            JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobErrorHandlerType("IGNORE").build();
+            jobErrorHandlerReloadable.init(jobConfig);
+            JobErrorHandler expected = jobErrorHandlerReloadable.getInstance();
+            jobErrorHandlerReloadable.reloadIfNecessary(jobConfig);
+            JobErrorHandler actual = jobErrorHandlerReloadable.getInstance();
+            assertThat(actual, is(expected));
+        }
     }
     
     @Test
     void assertShutdown() {
-        JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable();
-        setField(jobErrorHandlerReloadable, "jobErrorHandler", 
mockJobErrorHandler);
-        jobErrorHandlerReloadable.close();
-        verify(mockJobErrorHandler).close();
+        try (JobErrorHandlerReloadable jobErrorHandlerReloadable = new 
JobErrorHandlerReloadable()) {
+            setField(jobErrorHandlerReloadable, "jobErrorHandler", 
jobErrorHandler);
+            jobErrorHandlerReloadable.close();
+            verify(jobErrorHandler).close();
+        }
     }
     
     @SneakyThrows
diff --git 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandlerTest.java
index fb92dbbe2..7bb3f14d9 100644
--- 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/IgnoreJobErrorHandlerTest.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.error.handler.general;
 
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import java.util.Properties;
@@ -27,7 +27,6 @@ class IgnoreJobErrorHandlerTest {
     
     @Test
     void assertHandleException() {
-        JobErrorHandlerFactory.createHandler("IGNORE", new Properties())
-                .orElseThrow(() -> new JobConfigurationException("IGNORE error 
handler not found.")).handleException("test_job", new RuntimeException("test"));
+        TypedSPILoader.getService(JobErrorHandler.class, "IGNORE", new 
Properties()).handleException("test_job", new RuntimeException("test"));
     }
 }
diff --git 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandlerTest.java
index f5bf33512..64bd48d02 100644
--- 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/LogJobErrorHandlerTest.java
@@ -20,8 +20,8 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.general;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -52,7 +52,7 @@ class LogJobErrorHandlerTest {
     
     @Test
     void assertHandleException() {
-        LogJobErrorHandler actual = (LogJobErrorHandler) 
JobErrorHandlerFactory.createHandler("LOG", new Properties()).orElseThrow(() -> 
new JobConfigurationException("LOG error handler not found."));
+        LogJobErrorHandler actual = (LogJobErrorHandler) 
TypedSPILoader.getService(JobErrorHandler.class, "LOG", new Properties());
         Throwable cause = new RuntimeException("test");
         actual.handleException("test_job", cause);
         assertThat(appenderList.size(), is(1));
diff --git 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandlerTest.java
index c9bfaa7d4..8b8da2238 100644
--- 
a/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/general/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/general/ThrowJobErrorHandlerTest.java
@@ -17,9 +17,9 @@
 
 package org.apache.shardingsphere.elasticjob.error.handler.general;
 
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import java.util.Properties;
@@ -30,7 +30,6 @@ class ThrowJobErrorHandlerTest {
     
     @Test
     void assertHandleException() {
-        assertThrows(JobSystemException.class, () -> 
JobErrorHandlerFactory.createHandler("THROW", new Properties())
-                .orElseThrow(() -> new JobConfigurationException("THROW error 
handler not found.")).handleException("test_job", new 
RuntimeException("test")));
+        assertThrows(JobSystemException.class, () -> 
TypedSPILoader.getService(JobErrorHandler.class, "THROW", new 
Properties()).handleException("test_job", new RuntimeException("test")));
     }
 }
diff --git 
a/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerPropertiesValidatorTest.java
 
b/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerPropertiesValidatorTest.java
index 590ede1cb..05882b65d 100644
--- 
a/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerPropertiesValidatorTest.java
+++ 
b/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerPropertiesValidatorTest.java
@@ -18,8 +18,7 @@
 package org.apache.shardingsphere.elasticjob.error.handler.wechat;
 
 import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerPropertiesValidator;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import java.util.Properties;
@@ -30,40 +29,26 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 class WechatJobErrorHandlerPropertiesValidatorTest {
     
-    @BeforeEach
-    void startup() {
-        
ElasticJobServiceLoader.registerTypedService(JobErrorHandlerPropertiesValidator.class);
-    }
-    
     @Test
     void assertValidateWithNormal() {
         Properties properties = new Properties();
         properties.setProperty(WechatPropertiesConstants.WEBHOOK, "webhook");
         
properties.setProperty(WechatPropertiesConstants.READ_TIMEOUT_MILLISECONDS, 
"1000");
         
properties.setProperty(WechatPropertiesConstants.CONNECT_TIMEOUT_MILLISECONDS, 
"2000");
-        WechatJobErrorHandlerPropertiesValidator actual = getValidator();
-        actual.validate(properties);
+        TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"WECHAT").validate(properties);
     }
     
     @Test
     void assertValidateWithPropsIsNull() {
-        assertThrows(NullPointerException.class, () -> {
-            WechatJobErrorHandlerPropertiesValidator actual = getValidator();
-            actual.validate(null);
-        });
+        assertThrows(NullPointerException.class, () -> 
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"WECHAT").validate(null));
     }
     
     @Test
     void assertValidateWithWebhookIsNull() {
-        WechatJobErrorHandlerPropertiesValidator actual = getValidator();
         try {
-            actual.validate(new Properties());
-        } catch (NullPointerException e) {
-            assertThat(e.getMessage(), is(String.format("The property `%s` is 
required.", WechatPropertiesConstants.WEBHOOK)));
+            
TypedSPILoader.getService(JobErrorHandlerPropertiesValidator.class, 
"WECHAT").validate(new Properties());
+        } catch (final NullPointerException ex) {
+            assertThat(ex.getMessage(), is(String.format("The property `%s` is 
required.", WechatPropertiesConstants.WEBHOOK)));
         }
     }
-    
-    private WechatJobErrorHandlerPropertiesValidator getValidator() {
-        return (WechatJobErrorHandlerPropertiesValidator) 
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandlerPropertiesValidator.class,
 "WECHAT", null).get();
-    }
 }
diff --git 
a/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerTest.java
 
b/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerTest.java
index b477210d4..72226574a 100644
--- 
a/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerTest.java
+++ 
b/ecosystem/error-handler/type/wechat/src/test/java/org/apache/shardingsphere/elasticjob/error/handler/wechat/WechatJobErrorHandlerTest.java
@@ -20,12 +20,12 @@ package 
org.apache.shardingsphere.elasticjob.error.handler.wechat;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
-import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
+import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import 
org.apache.shardingsphere.elasticjob.error.handler.wechat.fixture.WechatInternalController;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
 import org.apache.shardingsphere.elasticjob.restful.NettyRestfulService;
 import 
org.apache.shardingsphere.elasticjob.restful.NettyRestfulServiceConfiguration;
 import org.apache.shardingsphere.elasticjob.restful.RestfulService;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
@@ -114,7 +114,7 @@ class WechatJobErrorHandlerTest {
     }
     
     private WechatJobErrorHandler getWechatJobErrorHandler(final Properties 
props) {
-        return (WechatJobErrorHandler) 
JobErrorHandlerFactory.createHandler("WECHAT", props).orElseThrow(() -> new 
JobConfigurationException("WECHAT error handler not found."));
+        return (WechatJobErrorHandler) 
TypedSPILoader.getService(JobErrorHandler.class, "WECHAT", props);
     }
     
     private Properties createConfigurationProperties(final String webhook) {
diff --git 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
index b43cc2976..5c3e7dbb5 100644
--- 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
+++ 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
@@ -24,6 +24,7 @@ import 
org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import org.apache.shardingsphere.elasticjob.executor.context.ExecutorContext;
 import org.apache.shardingsphere.elasticjob.executor.item.JobItemExecutor;
 import 
org.apache.shardingsphere.elasticjob.executor.item.JobItemExecutorFactory;
+import 
org.apache.shardingsphere.elasticjob.executor.item.impl.TypedJobItemExecutor;
 import org.apache.shardingsphere.elasticjob.infra.env.IpUtils;
 import org.apache.shardingsphere.elasticjob.infra.exception.ExceptionUtils;
 import 
org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
@@ -31,6 +32,7 @@ import 
org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
 import 
org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent.ExecutionSource;
 import 
org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent.State;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.util.Collection;
 import java.util.Map;
@@ -59,7 +61,7 @@ public final class ElasticJobExecutor {
     }
     
     public ElasticJobExecutor(final String type, final JobConfiguration 
jobConfig, final JobFacade jobFacade) {
-        this(null, jobConfig, jobFacade, 
JobItemExecutorFactory.getExecutor(type));
+        this(null, jobConfig, jobFacade, 
TypedSPILoader.getService(TypedJobItemExecutor.class, type));
     }
     
     private ElasticJobExecutor(final ElasticJob elasticJob, final 
JobConfiguration jobConfig, final JobFacade jobFacade, final JobItemExecutor 
jobItemExecutor) {
diff --git 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/context/ExecutorContext.java
 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/context/ExecutorContext.java
index 38786c619..2e5c1ba04 100644
--- 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/context/ExecutorContext.java
+++ 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/context/ExecutorContext.java
@@ -19,14 +19,11 @@ package 
org.apache.shardingsphere.elasticjob.executor.context;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.infra.context.Reloadable;
-import 
org.apache.shardingsphere.elasticjob.infra.context.ReloadablePostProcessor;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
+import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
 import java.util.Properties;
-import java.util.ServiceLoader;
 
 /**
  * Executor context.
@@ -36,22 +33,10 @@ import java.util.ServiceLoader;
  */
 public final class ExecutorContext {
     
-    static {
-        ElasticJobServiceLoader.registerTypedService(Reloadable.class);
-    }
-    
-    private final Map<String, Reloadable<?>> reloadableItems = new 
LinkedHashMap<>();
-    
     public ExecutorContext(final JobConfiguration jobConfig) {
-        ServiceLoader.load(Reloadable.class).forEach(each -> {
-            ElasticJobServiceLoader.newTypedServiceInstance(Reloadable.class, 
each.getType(), new Properties())
-                    .ifPresent(reloadable -> 
reloadableItems.put(reloadable.getType(), reloadable));
-        });
-        initReloadable(jobConfig);
-    }
-    
-    private void initReloadable(final JobConfiguration jobConfig) {
-        reloadableItems.values().stream().filter(each -> each instanceof 
ReloadablePostProcessor).forEach(each -> ((ReloadablePostProcessor) 
each).init(jobConfig));
+        for (Reloadable<?> each : 
ShardingSphereServiceLoader.getServiceInstances(Reloadable.class)) {
+            each.init(jobConfig);
+        }
     }
     
     /**
@@ -60,26 +45,26 @@ public final class ExecutorContext {
      * @param jobConfiguration job configuration
      */
     public void reloadIfNecessary(final JobConfiguration jobConfiguration) {
-        reloadableItems.values().forEach(each -> 
each.reloadIfNecessary(jobConfiguration));
+        
ShardingSphereServiceLoader.getServiceInstances(Reloadable.class).forEach(each 
-> each.reloadIfNecessary(jobConfiguration));
     }
     
     /**
      * Get instance.
      *
      * @param targetClass target class
-     * @param <T>         target type
+     * @param <T> target type
      * @return instance
      */
     @SuppressWarnings("unchecked")
     public <T> T get(final Class<T> targetClass) {
-        return (T) reloadableItems.get(targetClass.getName()).getInstance();
+        return (T) TypedSPILoader.getService(Reloadable.class, targetClass, 
new Properties()).getInstance();
     }
     
     /**
      * Shutdown all closeable instances.
      */
     public void shutdown() {
-        for (Reloadable<?> each : reloadableItems.values()) {
+        for (Reloadable<?> each : 
ShardingSphereServiceLoader.getServiceInstances(Reloadable.class)) {
             try {
                 each.close();
             } catch (final IOException ignored) {
diff --git 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactory.java
 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactory.java
index 4d4ed138f..9bf125e44 100644
--- 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactory.java
+++ 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactory.java
@@ -20,10 +20,8 @@ package org.apache.shardingsphere.elasticjob.executor.item;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
 import 
org.apache.shardingsphere.elasticjob.executor.item.impl.ClassedJobItemExecutor;
-import 
org.apache.shardingsphere.elasticjob.executor.item.impl.TypedJobItemExecutor;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
+import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -40,7 +38,6 @@ public final class JobItemExecutorFactory {
     private static final Map<Class, ClassedJobItemExecutor> CLASSED_EXECUTORS 
= new HashMap<>();
     
     static {
-        
ElasticJobServiceLoader.registerTypedService(TypedJobItemExecutor.class);
         ServiceLoader.load(ClassedJobItemExecutor.class).forEach(each -> 
CLASSED_EXECUTORS.put(each.getElasticJobClass(), each));
     }
     
@@ -59,15 +56,4 @@ public final class JobItemExecutorFactory {
         }
         throw new JobConfigurationException("Can not find executor for elastic 
job class `%s`", elasticJobClass.getName());
     }
-    
-    /**
-     * Get executor.
-     *
-     * @param elasticJobType elastic job type
-     * @return job item executor
-     */
-    public static JobItemExecutor getExecutor(final String elasticJobType) {
-        return 
ElasticJobServiceLoader.getCachedTypedServiceInstance(TypedJobItemExecutor.class,
 elasticJobType)
-                .orElseThrow(() -> new JobConfigurationException("Cannot find 
executor for elastic job type `%s`", elasticJobType));
-    }
 }
diff --git 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/impl/TypedJobItemExecutor.java
 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/impl/TypedJobItemExecutor.java
index fba87a4d6..32091f40a 100644
--- 
a/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/impl/TypedJobItemExecutor.java
+++ 
b/ecosystem/executor/kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/item/impl/TypedJobItemExecutor.java
@@ -19,10 +19,12 @@ package 
org.apache.shardingsphere.elasticjob.executor.item.impl;
 
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.executor.item.JobItemExecutor;
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 /**
  * Typed job item executor.
  */
+@SingletonSPI
 public interface TypedJobItemExecutor extends JobItemExecutor<ElasticJob>, 
TypedSPI {
 }
diff --git 
a/ecosystem/executor/kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactoryTest.java
 
b/ecosystem/executor/kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactoryTest.java
index bd6b3dd15..0695a8bd2 100644
--- 
a/ecosystem/executor/kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactoryTest.java
+++ 
b/ecosystem/executor/kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/item/JobItemExecutorFactoryTest.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.elasticjob.executor.item;
 
 import 
org.apache.shardingsphere.elasticjob.executor.fixture.executor.ClassedFooJobExecutor;
-import 
org.apache.shardingsphere.elasticjob.executor.fixture.executor.TypedFooJobExecutor;
 import 
org.apache.shardingsphere.elasticjob.executor.fixture.job.DetailedFooJob;
 import org.apache.shardingsphere.elasticjob.executor.fixture.job.FailedJob;
 import org.apache.shardingsphere.elasticjob.executor.fixture.job.FooJob;
@@ -45,14 +44,4 @@ class JobItemExecutorFactoryTest {
     void assertGetExecutorByClassSuccessWithSubClass() {
         assertThat(JobItemExecutorFactory.getExecutor(DetailedFooJob.class), 
instanceOf(ClassedFooJobExecutor.class));
     }
-    
-    @Test
-    void assertGetExecutorByTypeFailureWithInvalidType() {
-        assertThrows(JobConfigurationException.class, () -> 
JobItemExecutorFactory.getExecutor("FAIL"));
-    }
-    
-    @Test
-    void assertGetExecutorByTypeSuccess() {
-        assertThat(JobItemExecutorFactory.getExecutor("FOO"), 
instanceOf(TypedFooJobExecutor.class));
-    }
 }
diff --git a/infra/pom.xml b/infra/pom.xml
index b2cc16cb0..3e57c5d38 100644
--- a/infra/pom.xml
+++ b/infra/pom.xml
@@ -33,6 +33,11 @@
             <version>${project.parent.version}</version>
         </dependency>
         
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-infra-spi</artifactId>
+        </dependency>
+        
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadable.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadable.java
index 31de96058..f504f9662 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadable.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadable.java
@@ -17,12 +17,11 @@
 
 package org.apache.shardingsphere.elasticjob.infra.concurrent;
 
-import com.google.common.base.Strings;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.infra.context.Reloadable;
-import 
org.apache.shardingsphere.elasticjob.infra.context.ReloadablePostProcessor;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandlerFactory;
+import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.util.Optional;
 import java.util.concurrent.ExecutorService;
@@ -31,36 +30,31 @@ import java.util.concurrent.ExecutorService;
  * Executor service reloadable.
  */
 @Slf4j
-public final class ExecutorServiceReloadable implements 
Reloadable<ExecutorService>, ReloadablePostProcessor {
+public final class ExecutorServiceReloadable implements 
Reloadable<ExecutorService> {
     
-    private String jobExecutorServiceHandlerType;
+    private JobExecutorServiceHandler jobExecutorServiceHandler;
     
     private ExecutorService executorService;
     
     @Override
     public void init(final JobConfiguration jobConfig) {
-        jobExecutorServiceHandlerType = 
Strings.isNullOrEmpty(jobConfig.getJobExecutorServiceHandlerType())
-                ? JobExecutorServiceHandlerFactory.DEFAULT_HANDLER
-                : jobConfig.getJobExecutorServiceHandlerType();
-        executorService = 
JobExecutorServiceHandlerFactory.getHandler(jobExecutorServiceHandlerType).createExecutorService(jobConfig.getJobName());
+        jobExecutorServiceHandler = 
TypedSPILoader.getService(JobExecutorServiceHandler.class, 
jobConfig.getJobExecutorServiceHandlerType());
+        executorService = 
jobExecutorServiceHandler.createExecutorService(jobConfig.getJobName());
     }
     
     @Override
     public synchronized void reloadIfNecessary(final JobConfiguration 
jobConfig) {
-        String newJobExecutorServiceHandlerType = 
Strings.isNullOrEmpty(jobConfig.getJobExecutorServiceHandlerType())
-                ? JobExecutorServiceHandlerFactory.DEFAULT_HANDLER
-                : jobConfig.getJobExecutorServiceHandlerType();
-        if 
(newJobExecutorServiceHandlerType.equals(jobExecutorServiceHandlerType)) {
+        if 
(jobExecutorServiceHandler.getType().equals(jobConfig.getJobExecutorServiceHandlerType()))
 {
             return;
         }
-        log.debug("JobExecutorServiceHandler reload occurred in the job '{}'. 
Change from '{}' to '{}'.", jobConfig.getJobName(), 
jobExecutorServiceHandlerType, newJobExecutorServiceHandlerType);
-        reload(newJobExecutorServiceHandlerType, jobConfig.getJobName());
+        log.debug("JobExecutorServiceHandler reload occurred in the job '{}'. 
Change from '{}' to '{}'.",
+                jobConfig.getJobName(), jobExecutorServiceHandler.getType(), 
jobConfig.getJobExecutorServiceHandlerType());
+        reload(jobConfig.getJobExecutorServiceHandlerType(), 
jobConfig.getJobName());
     }
     
     private void reload(final String jobExecutorServiceHandlerType, final 
String jobName) {
         executorService.shutdown();
-        this.jobExecutorServiceHandlerType = jobExecutorServiceHandlerType;
-        executorService = 
JobExecutorServiceHandlerFactory.getHandler(jobExecutorServiceHandlerType).createExecutorService(jobName);
+        executorService = 
TypedSPILoader.getService(JobExecutorServiceHandler.class, 
jobExecutorServiceHandlerType).createExecutorService(jobName);
     }
     
     @Override
@@ -74,7 +68,7 @@ public final class ExecutorServiceReloadable implements 
Reloadable<ExecutorServi
     }
     
     @Override
-    public String getType() {
-        return ExecutorService.class.getName();
+    public Class<ExecutorService> getType() {
+        return ExecutorService.class;
     }
 }
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/Reloadable.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/Reloadable.java
index 22e901500..f0a5d5218 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/Reloadable.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/Reloadable.java
@@ -18,7 +18,8 @@
 package org.apache.shardingsphere.elasticjob.infra.context;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 import java.io.Closeable;
 
@@ -27,14 +28,22 @@ import java.io.Closeable;
  *
  * @param <T> reload target
  */
+@SingletonSPI
 public interface Reloadable<T> extends TypedSPI, Closeable {
     
+    /**
+     * Initialize reloadable.
+     *
+     * @param jobConfig job configuration
+     */
+    void init(JobConfiguration jobConfig);
+    
     /**
      * Reload if necessary.
      *
-     * @param jobConfiguration job configuration
+     * @param jobConfig job configuration
      */
-    void reloadIfNecessary(JobConfiguration jobConfiguration);
+    void reloadIfNecessary(JobConfiguration jobConfig);
     
     /**
      * Get target instance.
@@ -42,4 +51,7 @@ public interface Reloadable<T> extends TypedSPI, Closeable {
      * @return instance
      */
     T getInstance();
+    
+    @Override
+    Class<T> getType();
 }
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/ReloadablePostProcessor.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/ReloadablePostProcessor.java
deleted file mode 100644
index 8dc86d20c..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/context/ReloadablePostProcessor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.context;
-
-import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-
-/**
- * Reloadable post processor.
- */
-public interface ReloadablePostProcessor {
-    
-    /**
-     * Initialize reloadable.
-     *
-     * @param jobConfig job configuration
-     */
-    void init(JobConfiguration jobConfig);
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategy.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategy.java
index 70e4b704a..d230c09a1 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategy.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategy.java
@@ -17,7 +17,7 @@
 
 package org.apache.shardingsphere.elasticjob.infra.handler.sharding;
 
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 import java.util.List;
 import java.util.Map;
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactory.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactory.java
deleted file mode 100644
index 628e0f43e..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.handler.sharding;
-
-import com.google.common.base.Strings;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-
-/**
- * Job sharding strategy factory.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class JobShardingStrategyFactory {
-    
-    private static final String DEFAULT_STRATEGY = "AVG_ALLOCATION";
-    
-    static {
-        
ElasticJobServiceLoader.registerTypedService(JobShardingStrategy.class);
-    }
-    
-    /**
-     * Get job sharding strategy.
-     * 
-     * @param type job sharding strategy type
-     * @return job sharding strategy
-     */
-    public static JobShardingStrategy getStrategy(final String type) {
-        if (Strings.isNullOrEmpty(type)) {
-            return 
ElasticJobServiceLoader.getCachedTypedServiceInstance(JobShardingStrategy.class,
 DEFAULT_STRATEGY).get();
-        }
-        return 
ElasticJobServiceLoader.getCachedTypedServiceInstance(JobShardingStrategy.class,
 type)
-                .orElseThrow(() -> new JobConfigurationException("Cannot find 
sharding strategy using type '%s'.", type));
-    }
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/impl/AverageAllocationJobShardingStrategy.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/impl/AverageAllocationJobShardingStrategy.java
index 3e2bcc2c2..27c24fe85 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/impl/AverageAllocationJobShardingStrategy.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/impl/AverageAllocationJobShardingStrategy.java
@@ -32,9 +32,7 @@ import java.util.Map;
  * <p>
  * If the job server number and sharding count cannot be divided, 
  * the redundant sharding item that cannot be divided will be added to the 
server with small sequence number in turn.
- * 
  * For example:
- * 
  * 1. If there are 3 job servers and the total sharding count is 9, each job 
server is divided into: 1=[0,1,2], 2=[3,4,5], 3=[6,7,8];
  * 2. If there are 3 job servers and the total sharding count is 8, each job 
server is divided into: 1=[0,1,6], 2=[2,3,7], 3=[4,5];
  * 3. If there are 3 job servers and the total sharding count is 10, each job 
server is divided into: 1=[0,1,2,9], 2=[3,4,5], 3=[6,7,8].
@@ -82,4 +80,9 @@ public final class AverageAllocationJobShardingStrategy 
implements JobShardingSt
     public String getType() {
         return "AVG_ALLOCATION";
     }
+    
+    @Override
+    public boolean isDefault() {
+        return true;
+    }
 }
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandler.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandler.java
index 39c1f642a..4b26511fd 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandler.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandler.java
@@ -17,13 +17,15 @@
 
 package org.apache.shardingsphere.elasticjob.infra.handler.threadpool;
 
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 import java.util.concurrent.ExecutorService;
 
 /**
  * Job executor service handler.
  */
+@SingletonSPI
 public interface JobExecutorServiceHandler extends TypedSPI {
     
     /**
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactory.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactory.java
deleted file mode 100644
index 839c7baff..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.handler.threadpool;
-
-import com.google.common.base.Strings;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
-
-/**
- * Job executor service handler factory.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class JobExecutorServiceHandlerFactory {
-    
-    public static final String DEFAULT_HANDLER = "CPU";
-    
-    static {
-        
ElasticJobServiceLoader.registerTypedService(JobExecutorServiceHandler.class);
-    }
-    
-    /**
-     * Get job executor service handler.
-     *
-     * @param type executor service handler type
-     * @return executor service handler
-     */
-    public static JobExecutorServiceHandler getHandler(final String type) {
-        if (Strings.isNullOrEmpty(type)) {
-            return 
ElasticJobServiceLoader.getCachedTypedServiceInstance(JobExecutorServiceHandler.class,
 DEFAULT_HANDLER).get();
-        }
-        return 
ElasticJobServiceLoader.getCachedTypedServiceInstance(JobExecutorServiceHandler.class,
 type)
-                .orElseThrow(() -> new JobConfigurationException("Cannot find 
executor service handler using type '%s'.", type));
-    }
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandler.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandler.java
index 959f84505..70d39ce64 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandler.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandler.java
@@ -31,4 +31,9 @@ public final class CPUUsageJobExecutorServiceHandler extends 
AbstractJobExecutor
     public String getType() {
         return "CPU";
     }
+    
+    @Override
+    public boolean isDefault() {
+        return true;
+    }
 }
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
index 4fc1b249d..87eabd3f1 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
@@ -17,7 +17,7 @@
 
 package org.apache.shardingsphere.elasticjob.infra.listener;
 
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 /**
  * ElasticJob listener.
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
index b5aab2459..a6fe70e0c 100644
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
+++ 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
@@ -19,10 +19,9 @@ package org.apache.shardingsphere.elasticjob.infra.listener;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.util.Optional;
-import java.util.Properties;
 
 /**
  * Job listener factory.
@@ -30,10 +29,6 @@ import java.util.Properties;
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public final class ElasticJobListenerFactory {
     
-    static {
-        ElasticJobServiceLoader.registerTypedService(ElasticJobListener.class);
-    }
-    
     /**
      * Create a job listener instance.
      *
@@ -41,6 +36,6 @@ public final class ElasticJobListenerFactory {
      * @return optional job listener instance
      */
     public static Optional<ElasticJobListener> createListener(final String 
type) {
-        return 
ElasticJobServiceLoader.newTypedServiceInstance(ElasticJobListener.class, type, 
new Properties());
+        return TypedSPILoader.findService(ElasticJobListener.class, type);
     }
 }
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoader.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoader.java
deleted file mode 100644
index 6ba4cfaf3..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoader.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import 
org.apache.shardingsphere.elasticjob.infra.spi.exception.ServiceLoaderInstantiationException;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.ServiceLoader;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * ElasticJob service loader.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ElasticJobServiceLoader {
-    
-    private static final ConcurrentMap<Class<? extends TypedSPI>, 
ConcurrentMap<String, TypedSPI>> TYPED_SERVICES = new ConcurrentHashMap<>();
-    
-    private static final ConcurrentMap<Class<? extends TypedSPI>, 
ConcurrentMap<String, Class<? extends TypedSPI>>> TYPED_SERVICE_CLASSES = new 
ConcurrentHashMap<>();
-    
-    /**
-     * Register typeSPI service.
-     *
-     * @param typedService typed service
-     * @param <T> class of service
-     */
-    public static <T extends TypedSPI> void registerTypedService(final 
Class<T> typedService) {
-        if (TYPED_SERVICES.containsKey(typedService)) {
-            return;
-        }
-        ServiceLoader.load(typedService).forEach(each -> 
registerTypedServiceClass(typedService, each));
-    }
-    
-    private static <T extends TypedSPI> void registerTypedServiceClass(final 
Class<T> typedService, final TypedSPI instance) {
-        TYPED_SERVICES.computeIfAbsent(typedService, unused -> new 
ConcurrentHashMap<>()).putIfAbsent(instance.getType(), instance);
-        TYPED_SERVICE_CLASSES.computeIfAbsent(typedService, unused -> new 
ConcurrentHashMap<>()).putIfAbsent(instance.getType(), instance.getClass());
-    }
-    
-    /**
-     * Get cached typed instance.
-     *
-     * @param typedServiceInterface typed service interface
-     * @param type type
-     * @param <T> class of service
-     * @return cached typed service instance
-     */
-    public static <T extends TypedSPI> Optional<T> 
getCachedTypedServiceInstance(final Class<T> typedServiceInterface, final 
String type) {
-        return 
Optional.ofNullable(TYPED_SERVICES.get(typedServiceInterface)).map(services -> 
(T) services.get(type));
-    }
-    
-    /**
-     * New typed instance.
-     *
-     * @param typedServiceInterface typed service interface
-     * @param type type
-     * @param props properties
-     * @param <T> class of service
-     * @return new typed service instance
-     */
-    public static <T extends TypedSPI> Optional<T> 
newTypedServiceInstance(final Class<T> typedServiceInterface, final String 
type, final Properties props) {
-        Optional<T> result = 
Optional.ofNullable(TYPED_SERVICE_CLASSES.get(typedServiceInterface)).map(serviceClasses
 -> serviceClasses.get(type)).map(clazz -> (T) newServiceInstance(clazz));
-        if (result.isPresent() && result.get() instanceof SPIPostProcessor) {
-            ((SPIPostProcessor) result.get()).init(props);
-        }
-        return result;
-    }
-    
-    private static Object newServiceInstance(final Class<?> clazz) {
-        try {
-            return clazz.getConstructor().newInstance();
-        } catch (final InstantiationException | NoSuchMethodException | 
IllegalAccessException ex) {
-            throw new ServiceLoaderInstantiationException(clazz, ex);
-        } catch (final InvocationTargetException ex) {
-            throw new ServiceLoaderInstantiationException(clazz, 
ex.getCause());
-        }
-    }
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/SPIPostProcessor.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/SPIPostProcessor.java
deleted file mode 100644
index 1c4d27e20..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/SPIPostProcessor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi;
-
-import java.util.Properties;
-
-/**
- * SPI post processor.
- */
-public interface SPIPostProcessor {
-    
-    /**
-     * Initialize SPI instance.
-     * 
-     * @param props properties
-     */
-    void init(Properties props);
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/TypedSPI.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/TypedSPI.java
deleted file mode 100644
index e322e94d1..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/TypedSPI.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi;
-
-/**
- * Type based SPI.
- */
-public interface TypedSPI {
-    
-    /**
-     * Get type.
-     *
-     * @return type
-     */
-    String getType();
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/exception/ServiceLoaderInstantiationException.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/exception/ServiceLoaderInstantiationException.java
deleted file mode 100644
index 37ba5f006..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/spi/exception/ServiceLoaderInstantiationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi.exception;
-
-/**
- * Service loader instantiation exception.
- */
-public final class ServiceLoaderInstantiationException extends 
RuntimeException {
-    
-    private static final long serialVersionUID = -2949903598320994076L;
-    
-    public ServiceLoaderInstantiationException(final Class<?> clazz, final 
Throwable cause) {
-        super(String.format("Can not find public no args constructor for SPI 
class `%s`", clazz.getName()), cause);
-    }
-}
diff --git 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/validator/JobPropertiesValidator.java
 
b/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/validator/JobPropertiesValidator.java
deleted file mode 100644
index f3cbfd1ed..000000000
--- 
a/infra/src/main/java/org/apache/shardingsphere/elasticjob/infra/validator/JobPropertiesValidator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.validator;
-
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
-
-import java.util.Properties;
-
-/**
- * Job properties validator.
- */
-public interface JobPropertiesValidator extends TypedSPI {
-    
-    /**
-     * Validate job properties.
-     * 
-     * @param props job properties
-     */
-    void validate(Properties props);
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadableTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadableTest.java
index c7856ef70..4c30370b8 100644
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadableTest.java
+++ 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/concurrent/ExecutorServiceReloadableTest.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.elasticjob.infra.concurrent;
 
 import lombok.SneakyThrows;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
+import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandler;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
@@ -32,7 +33,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 class ExecutorServiceReloadableTest {
@@ -42,22 +45,25 @@ class ExecutorServiceReloadableTest {
     
     @Test
     void assertInitialize() {
-        ExecutorServiceReloadable executorServiceReloadable = new 
ExecutorServiceReloadable();
-        String jobExecutorServiceHandlerType = "SINGLE_THREAD";
-        JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobExecutorServiceHandlerType(jobExecutorServiceHandlerType).build();
-        assertNull(executorServiceReloadable.getInstance());
-        executorServiceReloadable.init(jobConfig);
-        ExecutorService actual = executorServiceReloadable.getInstance();
-        assertNotNull(actual);
-        assertFalse(actual.isShutdown());
-        assertFalse(actual.isTerminated());
-        actual.shutdown();
+        try (ExecutorServiceReloadable executorServiceReloadable = new 
ExecutorServiceReloadable()) {
+            String jobExecutorServiceHandlerType = "SINGLE_THREAD";
+            JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobExecutorServiceHandlerType(jobExecutorServiceHandlerType).build();
+            assertNull(executorServiceReloadable.getInstance());
+            executorServiceReloadable.init(jobConfig);
+            ExecutorService actual = executorServiceReloadable.getInstance();
+            assertNotNull(actual);
+            assertFalse(actual.isShutdown());
+            assertFalse(actual.isTerminated());
+            actual.shutdown();
+        }
     }
     
     @Test
     void assertReload() {
         ExecutorServiceReloadable executorServiceReloadable = new 
ExecutorServiceReloadable();
-        setField(executorServiceReloadable, "jobExecutorServiceHandlerType", 
"mock");
+        JobExecutorServiceHandler jobExecutorServiceHandler = 
mock(JobExecutorServiceHandler.class);
+        when(jobExecutorServiceHandler.getType()).thenReturn("mock");
+        setField(executorServiceReloadable, "jobExecutorServiceHandler", 
jobExecutorServiceHandler);
         setField(executorServiceReloadable, "executorService", 
mockExecutorService);
         JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).build();
         executorServiceReloadable.reloadIfNecessary(jobConfig);
@@ -70,14 +76,15 @@ class ExecutorServiceReloadableTest {
     
     @Test
     void assertUnnecessaryToReload() {
-        ExecutorServiceReloadable executorServiceReloadable = new 
ExecutorServiceReloadable();
-        JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).build();
-        executorServiceReloadable.init(jobConfig);
-        ExecutorService expected = executorServiceReloadable.getInstance();
-        executorServiceReloadable.reloadIfNecessary(jobConfig);
-        ExecutorService actual = executorServiceReloadable.getInstance();
-        assertThat(actual, is(expected));
-        actual.shutdown();
+        try (ExecutorServiceReloadable executorServiceReloadable = new 
ExecutorServiceReloadable()) {
+            JobConfiguration jobConfig = JobConfiguration.newBuilder("job", 
1).jobExecutorServiceHandlerType("CPU").build();
+            executorServiceReloadable.init(jobConfig);
+            ExecutorService expected = executorServiceReloadable.getInstance();
+            executorServiceReloadable.reloadIfNecessary(jobConfig);
+            ExecutorService actual = executorServiceReloadable.getInstance();
+            assertThat(actual, is(expected));
+            actual.shutdown();
+        }
     }
     
     @Test
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactoryTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactoryTest.java
deleted file mode 100644
index 9db6376ab..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/sharding/JobShardingStrategyFactoryTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.handler.sharding;
-
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.sharding.impl.AverageAllocationJobShardingStrategy;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.sharding.impl.OdevitySortByNameJobShardingStrategy;
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-class JobShardingStrategyFactoryTest {
-    
-    @Test
-    void assertGetDefaultStrategy() {
-        assertThat(JobShardingStrategyFactory.getStrategy(null), 
instanceOf(AverageAllocationJobShardingStrategy.class));
-    }
-    
-    @Test
-    void assertGetInvalidStrategy() {
-        assertThrows(JobConfigurationException.class, () -> 
JobShardingStrategyFactory.getStrategy("INVALID"));
-    }
-    
-    @Test
-    void assertGetStrategy() {
-        assertThat(JobShardingStrategyFactory.getStrategy("ODEVITY"), 
instanceOf(OdevitySortByNameJobShardingStrategy.class));
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactoryTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactoryTest.java
deleted file mode 100644
index 25758af9e..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/JobExecutorServiceHandlerFactoryTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.handler.threadpool;
-
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.impl.CPUUsageJobExecutorServiceHandler;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.impl.SingleThreadJobExecutorServiceHandler;
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-class JobExecutorServiceHandlerFactoryTest {
-    
-    @Test
-    void assertGetDefaultHandler() {
-        assertThat(JobExecutorServiceHandlerFactory.getHandler(""), 
instanceOf(CPUUsageJobExecutorServiceHandler.class));
-    }
-    
-    @Test
-    void assertGetInvalidHandler() {
-        assertThrows(JobConfigurationException.class, () -> 
JobExecutorServiceHandlerFactory.getHandler("INVALID"));
-    }
-    
-    @Test
-    void assertGetHandler() {
-        
assertThat(JobExecutorServiceHandlerFactory.getHandler("SINGLE_THREAD"), 
instanceOf(SingleThreadJobExecutorServiceHandler.class));
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandlerTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandlerTest.java
index 6bea560a9..ff9d77639 100644
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandlerTest.java
+++ 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/CPUUsageJobExecutorServiceHandlerTest.java
@@ -17,7 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.infra.handler.threadpool.impl;
 
-import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandlerFactory;
+import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -27,8 +28,6 @@ class CPUUsageJobExecutorServiceHandlerTest {
     
     @Test
     void assertGetPoolSizeAndType() {
-        CPUUsageJobExecutorServiceHandler cpuUsageJobExecutorServiceHandler = 
(CPUUsageJobExecutorServiceHandler) 
JobExecutorServiceHandlerFactory.getHandler("CPU");
-        assertThat(cpuUsageJobExecutorServiceHandler.getPoolSize(), 
is(Runtime.getRuntime().availableProcessors() * 2));
-        assertThat(cpuUsageJobExecutorServiceHandler.getType(), is("CPU"));
+        assertThat(((CPUUsageJobExecutorServiceHandler) 
TypedSPILoader.getService(JobExecutorServiceHandler.class, 
"CPU")).getPoolSize(), is(Runtime.getRuntime().availableProcessors() * 2));
     }
 }
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/SingleThreadJobExecutorServiceHandlerTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/SingleThreadJobExecutorServiceHandlerTest.java
index d0dd4ff31..45f754a15 100644
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/SingleThreadJobExecutorServiceHandlerTest.java
+++ 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/handler/threadpool/impl/SingleThreadJobExecutorServiceHandlerTest.java
@@ -17,7 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.infra.handler.threadpool.impl;
 
-import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandlerFactory;
+import 
org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandler;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -27,8 +28,6 @@ class SingleThreadJobExecutorServiceHandlerTest {
     
     @Test
     void assertGetPoolSizeAndType() {
-        SingleThreadJobExecutorServiceHandler 
singleThreadJobExecutorServiceHandler = (SingleThreadJobExecutorServiceHandler) 
JobExecutorServiceHandlerFactory.getHandler("SINGLE_THREAD");
-        assertThat(singleThreadJobExecutorServiceHandler.getPoolSize(), is(1));
-        assertThat(singleThreadJobExecutorServiceHandler.getType(), 
is("SINGLE_THREAD"));
+        assertThat(((SingleThreadJobExecutorServiceHandler) 
TypedSPILoader.getService(JobExecutorServiceHandler.class, 
"SINGLE_THREAD")).getPoolSize(), is(1));
     }
 }
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactoryTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactoryTest.java
deleted file mode 100644
index 669316cc8..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactoryTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.listener;
-
-import 
org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
-import 
org.apache.shardingsphere.elasticjob.infra.listener.fixture.FooElasticJobListener;
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-class ElasticJobListenerFactoryTest {
-    
-    @Test
-    void assertCreateInvalidJobListener() {
-        assertThrows(JobConfigurationException.class, () -> 
ElasticJobListenerFactory.createListener("INVALID").orElseThrow(() -> new 
JobConfigurationException("Invalid elastic job listener!")));
-    }
-    
-    @Test
-    void assertCreatJobListener() {
-        
assertThat(ElasticJobListenerFactory.createListener("fooElasticJobListener").orElse(null),
 instanceOf(FooElasticJobListener.class));
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/fixture/FooElasticJobListener.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/fixture/FooElasticJobListener.java
deleted file mode 100644
index f53ce97d2..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/fixture/FooElasticJobListener.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.listener.fixture;
-
-import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
-
-public final class FooElasticJobListener implements ElasticJobListener {
-    
-    @Override
-    public void beforeJobExecuted(final ShardingContexts shardingContexts) {
-    }
-    
-    @Override
-    public void afterJobExecuted(final ShardingContexts shardingContexts) {
-    }
-    
-    @Override
-    public String getType() {
-        return "fooElasticJobListener";
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoaderTest.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoaderTest.java
deleted file mode 100644
index e21af0f17..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/ElasticJobServiceLoaderTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi;
-
-import org.apache.shardingsphere.elasticjob.infra.spi.fixture.TypedFooService;
-import 
org.apache.shardingsphere.elasticjob.infra.spi.fixture.UnRegisteredTypedFooService;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import java.util.Properties;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-class ElasticJobServiceLoaderTest {
-    
-    @BeforeAll
-    static void register() {
-        ElasticJobServiceLoader.registerTypedService(TypedFooService.class);
-    }
-    
-    @Test
-    void assertGetCacheTypedService() {
-        
assertThat(ElasticJobServiceLoader.getCachedTypedServiceInstance(TypedFooService.class,
 "typedFooServiceImpl").orElse(null), instanceOf(TypedFooService.class));
-    }
-    
-    @Test
-    void assertNewTypedServiceInstance() {
-        
assertThat(ElasticJobServiceLoader.getCachedTypedServiceInstance(TypedFooService.class,
 "typedFooServiceImpl").orElse(null), instanceOf(TypedFooService.class));
-    }
-    
-    @Test
-    void assertGetCacheTypedServiceFailureWithUnRegisteredServiceInterface() {
-        Assertions.assertThrows(IllegalArgumentException.class, () -> 
ElasticJobServiceLoader.getCachedTypedServiceInstance(
-                UnRegisteredTypedFooService.class, 
"unRegisteredTypedFooServiceImpl").orElseThrow(IllegalArgumentException::new));
-    }
-    
-    @Test
-    void assertGetCacheTypedServiceFailureWithInvalidType() {
-        Assertions.assertThrows(IllegalArgumentException.class, () -> 
ElasticJobServiceLoader.getCachedTypedServiceInstance(
-                TypedFooService.class, 
"INVALID").orElseThrow(IllegalArgumentException::new));
-    }
-    
-    @Test
-    void 
assertNewTypedServiceInstanceFailureWithUnRegisteredServiceInterface() {
-        Assertions.assertThrows(IllegalArgumentException.class, () -> 
ElasticJobServiceLoader
-                .newTypedServiceInstance(UnRegisteredTypedFooService.class, 
"unRegisteredTypedFooServiceImpl", new 
Properties()).orElseThrow(IllegalArgumentException::new));
-    }
-    
-    @Test
-    void assertNewTypedServiceInstanceFailureWithInvalidType() {
-        Assertions.assertThrows(IllegalArgumentException.class, () -> 
ElasticJobServiceLoader.newTypedServiceInstance(
-                TypedFooService.class, "INVALID", new 
Properties()).orElseThrow(IllegalArgumentException::new));
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/TypedFooService.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/TypedFooService.java
deleted file mode 100644
index 5ed5219bb..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/TypedFooService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi.fixture;
-
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
-
-public interface TypedFooService extends TypedSPI {
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/UnRegisteredTypedFooService.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/UnRegisteredTypedFooService.java
deleted file mode 100644
index 32891da47..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/UnRegisteredTypedFooService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi.fixture;
-
-import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
-
-public interface UnRegisteredTypedFooService extends TypedSPI {
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/TypedFooServiceImpl.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/TypedFooServiceImpl.java
deleted file mode 100644
index 02fef2861..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/TypedFooServiceImpl.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi.fixture.impl;
-
-import org.apache.shardingsphere.elasticjob.infra.spi.fixture.TypedFooService;
-
-public final class TypedFooServiceImpl implements TypedFooService {
-    
-    @Override
-    public String getType() {
-        return "typedFooServiceImpl";
-    }
-}
diff --git 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/UnRegisteredTypedFooServiceImpl.java
 
b/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/UnRegisteredTypedFooServiceImpl.java
deleted file mode 100644
index c53e043b1..000000000
--- 
a/infra/src/test/java/org/apache/shardingsphere/elasticjob/infra/spi/fixture/impl/UnRegisteredTypedFooServiceImpl.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.infra.spi.fixture.impl;
-
-import 
org.apache.shardingsphere.elasticjob.infra.spi.fixture.UnRegisteredTypedFooService;
-
-public final class UnRegisteredTypedFooServiceImpl implements 
UnRegisteredTypedFooService {
-    
-    @Override
-    public String getType() {
-        return "unRegisteredTypedFooServiceImpl";
-    }
-}
diff --git 
a/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.TypedFooService
 
b/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.TypedFooService
deleted file mode 100644
index 9470ce82d..000000000
--- 
a/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.TypedFooService
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#  
-#     http://www.apache.org/licenses/LICENSE-2.0
-#  
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-org.apache.shardingsphere.elasticjob.infra.spi.fixture.impl.TypedFooServiceImpl
diff --git 
a/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.UnRegisteredTypedFooService
 
b/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.UnRegisteredTypedFooService
deleted file mode 100644
index 2d955a7c5..000000000
--- 
a/infra/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.spi.fixture.UnRegisteredTypedFooService
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#  
-#     http://www.apache.org/licenses/LICENSE-2.0
-#  
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-org.apache.shardingsphere.elasticjob.infra.spi.fixture.impl.UnRegisteredTypedFooServiceImpl
diff --git 
a/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/schedule/JobScheduler.java
 
b/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/schedule/JobScheduler.java
index 62b0975b9..76ef8fd7d 100644
--- 
a/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/schedule/JobScheduler.java
+++ 
b/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/schedule/JobScheduler.java
@@ -27,8 +27,6 @@ import 
org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
 import org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobInstance;
 import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
-import 
org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListenerFactory;
-import org.apache.shardingsphere.elasticjob.infra.spi.ElasticJobServiceLoader;
 import 
org.apache.shardingsphere.elasticjob.kernel.api.listener.AbstractDistributeOnceElasticJobListener;
 import 
org.apache.shardingsphere.elasticjob.kernel.internal.config.ConfigurationService;
 import 
org.apache.shardingsphere.elasticjob.kernel.internal.guarantee.GuaranteeService;
@@ -36,6 +34,7 @@ import 
org.apache.shardingsphere.elasticjob.kernel.internal.setup.JobClassNamePr
 import org.apache.shardingsphere.elasticjob.kernel.internal.setup.SetUpFacade;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 import org.apache.shardingsphere.elasticjob.tracing.api.TracingConfiguration;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.quartz.JobBuilder;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
@@ -53,10 +52,6 @@ import java.util.stream.Collectors;
  */
 public final class JobScheduler {
     
-    static {
-        
ElasticJobServiceLoader.registerTypedService(JobErrorHandlerPropertiesValidator.class);
-    }
-    
     private static final String JOB_EXECUTOR_DATA_MAP_KEY = "jobExecutor";
     
     @Getter
@@ -111,9 +106,7 @@ public final class JobScheduler {
     }
     
     private Collection<ElasticJobListener> getElasticJobListeners(final 
JobConfiguration jobConfig) {
-        return jobConfig.getJobListenerTypes().stream()
-                .map(type -> 
ElasticJobListenerFactory.createListener(type).orElseThrow(() -> new 
IllegalArgumentException(String.format("Can not find job listener type '%s'.", 
type))))
-                .collect(Collectors.toList());
+        return jobConfig.getJobListenerTypes().stream().map(each -> 
TypedSPILoader.getService(ElasticJobListener.class, 
each)).collect(Collectors.toList());
     }
     
     private Optional<TracingConfiguration<?>> findTracingConfiguration() {
@@ -126,7 +119,7 @@ public final class JobScheduler {
     
     private void validateJobErrorHandlerProperties() {
         if (null != jobConfig.getJobErrorHandlerType()) {
-            
ElasticJobServiceLoader.newTypedServiceInstance(JobErrorHandlerPropertiesValidator.class,
 jobConfig.getJobErrorHandlerType(), jobConfig.getProps())
+            
TypedSPILoader.findService(JobErrorHandlerPropertiesValidator.class, 
jobConfig.getJobErrorHandlerType(), jobConfig.getProps())
                     .ifPresent(validator -> 
validator.validate(jobConfig.getProps()));
         }
     }
diff --git 
a/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/sharding/ShardingService.java
 
b/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/sharding/ShardingService.java
index 4bde6078a..ca46e0152 100644
--- 
a/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/sharding/ShardingService.java
+++ 
b/kernel/src/main/java/org/apache/shardingsphere/elasticjob/kernel/internal/sharding/ShardingService.java
@@ -22,7 +22,6 @@ import 
org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.infra.concurrent.BlockUtils;
 import org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobInstance;
 import 
org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobShardingStrategy;
-import 
org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobShardingStrategyFactory;
 import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
 import 
org.apache.shardingsphere.elasticjob.kernel.internal.config.ConfigurationService;
 import 
org.apache.shardingsphere.elasticjob.kernel.internal.election.LeaderService;
@@ -34,6 +33,7 @@ import 
org.apache.shardingsphere.elasticjob.kernel.internal.storage.JobNodePath;
 import 
org.apache.shardingsphere.elasticjob.kernel.internal.storage.JobNodeStorage;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 import 
org.apache.shardingsphere.elasticjob.reg.base.transaction.TransactionOperation;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -121,7 +121,7 @@ public final class ShardingService {
         log.debug("Job '{}' sharding begin.", jobName);
         jobNodeStorage.fillEphemeralJobNode(ShardingNode.PROCESSING, "");
         resetShardingInfo(shardingTotalCount);
-        JobShardingStrategy jobShardingStrategy = 
JobShardingStrategyFactory.getStrategy(jobConfig.getJobShardingStrategyType());
+        JobShardingStrategy jobShardingStrategy = 
TypedSPILoader.getService(JobShardingStrategy.class, 
jobConfig.getJobShardingStrategyType());
         
jobNodeStorage.executeInTransaction(getShardingResultTransactionOperations(jobShardingStrategy.sharding(availableJobInstances,
 jobName, shardingTotalCount)));
         log.debug("Job '{}' sharding complete.", jobName);
     }
diff --git a/pom.xml b/pom.xml
index 7a40f8b82..8bafe3435 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         
         <!-- 3rd party library versions -->
+        <shardingsphere.version>5.4.1</shardingsphere.version>
         <guava.version>32.1.2-jre</guava.version>
         <commons-lang3.version>3.12.0</commons-lang3.version>
         <commons-codec.version>1.16.0</commons-codec.version>
@@ -123,6 +124,11 @@
     
     <dependencyManagement>
         <dependencies>
+            <dependency>
+                <groupId>org.apache.shardingsphere</groupId>
+                <artifactId>shardingsphere-infra-spi</artifactId>
+                <version>${shardingsphere.version}</version>
+            </dependency>
             <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
diff --git 
a/spring/namespace/src/main/java/org/apache/shardingsphere/elasticjob/spring/namespace/job/parser/JobBeanDefinitionParser.java
 
b/spring/namespace/src/main/java/org/apache/shardingsphere/elasticjob/spring/namespace/job/parser/JobBeanDefinitionParser.java
index 335deb77d..1a4172efa 100644
--- 
a/spring/namespace/src/main/java/org/apache/shardingsphere/elasticjob/spring/namespace/job/parser/JobBeanDefinitionParser.java
+++ 
b/spring/namespace/src/main/java/org/apache/shardingsphere/elasticjob/spring/namespace/job/parser/JobBeanDefinitionParser.java
@@ -28,7 +28,7 @@ import 
org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.ManagedList;
 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.xml.DomUtils;
 import org.w3c.dom.Element;
 
@@ -75,10 +75,15 @@ public final class JobBeanDefinitionParser extends 
AbstractBeanDefinitionParser
         
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.MISFIRE_ATTRIBUTE));
         
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.MAX_TIME_DIFF_SECONDS_ATTRIBUTE));
         
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.RECONCILE_INTERVAL_MINUTES));
-        
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.JOB_SHARDING_STRATEGY_TYPE_ATTRIBUTE));
-        
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.JOB_EXECUTOR_SERVICE_HANDLER_TYPE_ATTRIBUTE));
-        
result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.JOB_ERROR_HANDLER_TYPE_ATTRIBUTE));
-        if 
(StringUtils.isEmpty(element.getAttribute(JobBeanDefinitionTag.JOB_LISTENER_TYPES_ATTRIBUTE).trim()))
 {
+        result.addConstructorArgValue(
+                
element.hasAttribute(JobBeanDefinitionTag.JOB_SHARDING_STRATEGY_TYPE_ATTRIBUTE) 
? 
element.getAttribute(JobBeanDefinitionTag.JOB_SHARDING_STRATEGY_TYPE_ATTRIBUTE) 
: null);
+        result.addConstructorArgValue(
+                
element.hasAttribute(JobBeanDefinitionTag.JOB_EXECUTOR_SERVICE_HANDLER_TYPE_ATTRIBUTE)
+                        ? 
element.getAttribute(JobBeanDefinitionTag.JOB_EXECUTOR_SERVICE_HANDLER_TYPE_ATTRIBUTE)
+                        : null);
+        result.addConstructorArgValue(
+                
element.hasAttribute(JobBeanDefinitionTag.JOB_ERROR_HANDLER_TYPE_ATTRIBUTE) ? 
element.getAttribute(JobBeanDefinitionTag.JOB_ERROR_HANDLER_TYPE_ATTRIBUTE) : 
null);
+        if 
(ObjectUtils.isEmpty(element.getAttribute(JobBeanDefinitionTag.JOB_LISTENER_TYPES_ATTRIBUTE).trim()))
 {
             result.addConstructorArgValue(Collections.emptyList());
         } else {
             
result.addConstructorArgValue(Arrays.asList(element.getAttribute(JobBeanDefinitionTag.JOB_LISTENER_TYPES_ATTRIBUTE).split(",")));

Reply via email to