You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by te...@apache.org on 2020/09/23 08:43:23 UTC

[shardingsphere-elasticjob] branch master updated: Move ElasticJobListener to JobConfiguration (#1476)

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

technoboy 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 5661923  Move ElasticJobListener to JobConfiguration (#1476)
5661923 is described below

commit 56619236dc6bf6f7f35c585d88660ad53bad805d
Author: Tboy <gu...@immomo.com>
AuthorDate: Wed Sep 23 16:43:15 2020 +0800

    Move ElasticJobListener to JobConfiguration (#1476)
---
 .../elasticjob/api/JobConfiguration.java           | 20 +++++++-
 .../cloud/executor/local/LocalTaskExecutor.java    |  2 +-
 .../cloud/executor/prod/DaemonTaskScheduler.java   |  2 +-
 .../cloud/executor/prod/TaskExecutor.java          |  2 +-
 .../elasticjob/cloud/facade/CloudJobFacade.java    |  2 +-
 .../cloud/executor/facade/CloudJobFacadeTest.java  |  2 +-
 .../executor/prod/DaemonTaskSchedulerTest.java     |  2 +-
 .../executor/prod/TaskExecutorThreadTest.java      |  2 +-
 .../cloud/scheduler/mesos/TaskInfoData.java        |  2 +-
 .../mesos/TaskLaunchScheduledService.java          |  2 +-
 .../cloud/scheduler/mesos/TaskInfoDataTest.java    |  2 +-
 ...sphere.elasticjob.error.handler.JobErrorHandler | 18 ++++++++
 .../elasticjob/executor/ElasticJobExecutor.java    |  2 +-
 .../elasticjob/executor/JobFacade.java             |  2 +-
 .../executor/ElasticJobExecutorTest.java           |  2 +-
 .../infra}/listener/ElasticJobListener.java        |  6 ++-
 .../infra/listener/ElasticJobListenerFactory.java  | 53 ++++++++++++++++++++++
 .../infra}/listener/ShardingContexts.java          |  2 +-
 .../infra/pojo/JobConfigurationPOJO.java           |  7 ++-
 .../infra}/listener/ShardingContextsTest.java      |  2 +-
 .../infra/pojo/JobConfigurationPOJOTest.java       |  8 +++-
 .../api/bootstrap/impl/OneOffJobBootstrap.java     | 19 ++++----
 .../api/bootstrap/impl/ScheduleJobBootstrap.java   | 19 ++++----
 .../AbstractDistributeOnceElasticJobListener.java  |  4 +-
 .../guarantee/GuaranteeListenerManager.java        |  8 ++--
 .../lite/internal/listener/ListenerManager.java    |  6 +--
 .../lite/internal/schedule/JobScheduler.java       | 47 +++++++++----------
 .../lite/internal/schedule/LiteJobFacade.java      |  8 ++--
 .../lite/internal/setup/SetUpFacade.java           |  6 +--
 .../internal/sharding/ExecutionContextService.java |  2 +-
 .../lite/internal/sharding/ExecutionService.java   |  2 +-
 .../DistributeOnceElasticJobListenerTest.java      |  2 +-
 .../TestDistributeOnceElasticJobListener.java      | 11 ++++-
 .../listener/fixture/TestElasticJobListener.java   | 13 +++++-
 .../lite/integrate/BaseIntegrateTest.java          | 39 +++-------------
 .../disable/OneOffDisabledJobIntegrateTest.java    |  3 +-
 .../disable/ScheduleDisabledJobIntegrateTest.java  |  3 +-
 .../enable/OneOffEnabledJobIntegrateTest.java      |  3 +-
 .../enable/ScheduleEnabledJobIntegrateTest.java    |  3 +-
 .../TestDistributeOnceElasticJobListener.java      | 20 ++++----
 .../listener}/TestElasticJobListener.java          | 19 ++++----
 .../guarantee/GuaranteeListenerManagerTest.java    |  2 +-
 .../lite/internal/schedule/LiteJobFacadeTest.java  |  2 +-
 .../sharding/ExecutionContextServiceTest.java      |  2 +-
 .../internal/sharding/ExecutionServiceTest.java    |  2 +-
 ...re.elasticjob.infra.listener.ElasticJobListener | 21 +++++++++
 .../job/parser/JobBeanDefinitionParser.java        |  9 +++-
 .../namespace/job/tag/JobBeanDefinitionTag.java    |  2 +
 .../resources/META-INF/namespace/elasticjob.xsd    | 16 +------
 .../fixture/listener/SimpleCglibListener.java      |  9 +++-
 .../listener/SimpleJdkDynamicProxyListener.java    |  9 +++-
 .../namespace/fixture/listener/SimpleListener.java |  9 +++-
 .../fixture/listener/SimpleOnceListener.java       | 11 ++++-
 .../resources/META-INF/job/oneOffWithListener.xml  |  4 +-
 .../META-INF/job/oneOffWithListenerAndCglib.xml    |  3 +-
 .../job/oneOffWithListenerAndJdkDynamicProxy.xml   |  3 +-
 .../test/resources/META-INF/job/withListener.xml   |  4 +-
 .../META-INF/job/withListenerAndCglib.xml          |  3 +-
 .../job/withListenerAndJdkDynamicProxy.xml         |  3 +-
 ...re.elasticjob.infra.listener.ElasticJobListener | 21 +++++++++
 60 files changed, 326 insertions(+), 188 deletions(-)

diff --git a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/JobConfiguration.java b/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/JobConfiguration.java
index a567d02..9668ffb 100644
--- a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/JobConfiguration.java
+++ b/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/JobConfiguration.java
@@ -24,6 +24,9 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Properties;
 
 /**
@@ -59,6 +62,8 @@ public final class JobConfiguration {
     
     private final String jobErrorHandlerType;
     
+    private final Collection<String> jobListenerTypes;
+    
     private final String description;
     
     private final Properties props;
@@ -106,6 +111,8 @@ public final class JobConfiguration {
         private String jobExecutorServiceHandlerType;
         
         private String jobErrorHandlerType;
+    
+        private final Collection<String> jobListenerTypes = new ArrayList<>();
         
         private String description = "";
         
@@ -276,6 +283,17 @@ public final class JobConfiguration {
             this.jobErrorHandlerType = jobErrorHandlerType;
             return this;
         }
+    
+        /**
+         * Set job listener types.
+         *
+         * @param jobListenerTypes job listener types
+         * @return ElasticJob configuration builder
+         */
+        public Builder jobListenerTypes(final String... jobListenerTypes) {
+            this.jobListenerTypes.addAll(Arrays.asList(jobListenerTypes));
+            return this;
+        }
         
         /**
          * Set job description.
@@ -342,7 +360,7 @@ public final class JobConfiguration {
             Preconditions.checkArgument(shardingTotalCount > 0, "shardingTotalCount should larger than zero.");
             return new JobConfiguration(jobName, cron, shardingTotalCount, shardingItemParameters, jobParameter, 
                     monitorExecution, failover, misfire, maxTimeDiffSeconds, reconcileIntervalMinutes,
-                    jobShardingStrategyType, jobExecutorServiceHandlerType, jobErrorHandlerType, description, props, disabled, overwrite);
+                    jobShardingStrategyType, jobExecutorServiceHandlerType, jobErrorHandlerType, jobListenerTypes, description, props, disabled, overwrite);
         }
     }
 }
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/local/LocalTaskExecutor.java b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/local/LocalTaskExecutor.java
index b3f9888..9bb9559 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/local/LocalTaskExecutor.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/local/LocalTaskExecutor.java
@@ -21,11 +21,11 @@ import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.facade.CloudJobFacade;
 import org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.context.ShardingItemParameters;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
 
 import java.util.HashMap;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskScheduler.java b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskScheduler.java
index bc90ac1..1d78a52 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskScheduler.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskScheduler.java
@@ -23,11 +23,11 @@ import org.apache.mesos.ExecutorDriver;
 import org.apache.mesos.Protos;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.facade.CloudJobFacade;
 import org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.quartz.CronScheduleBuilder;
 import org.quartz.CronTrigger;
 import org.quartz.Job;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutor.java b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutor.java
index ee720b2..377fa37 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutor.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutor.java
@@ -29,12 +29,12 @@ import org.apache.mesos.Protos;
 import org.apache.mesos.Protos.TaskInfo;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.facade.CloudJobFacade;
 import org.apache.shardingsphere.elasticjob.executor.ElasticJobExecutor;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.concurrent.ElasticJobExecutorService;
 import org.apache.shardingsphere.elasticjob.infra.exception.ExceptionUtils;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.pojo.JobConfigurationPOJO;
 import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
 import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/facade/CloudJobFacade.java b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/facade/CloudJobFacade.java
index 7329e0b..383e5be 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/facade/CloudJobFacade.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/main/java/org/apache/shardingsphere/elasticjob/cloud/facade/CloudJobFacade.java
@@ -19,9 +19,9 @@ package org.apache.shardingsphere.elasticjob.cloud.facade;
 
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/facade/CloudJobFacadeTest.java b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/facade/CloudJobFacadeTest.java
index a38a6fb..d958c86 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/facade/CloudJobFacadeTest.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/facade/CloudJobFacadeTest.java
@@ -18,12 +18,12 @@
 package org.apache.shardingsphere.elasticjob.cloud.executor.facade;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.facade.CloudJobFacade;
 import org.apache.shardingsphere.elasticjob.dataflow.props.DataflowJobProperties;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.context.ExecutionType;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent.State;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskSchedulerTest.java b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskSchedulerTest.java
index 8b5fd31..e986d34 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskSchedulerTest.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/DaemonTaskSchedulerTest.java
@@ -24,10 +24,10 @@ import org.apache.mesos.Protos.TaskState;
 import org.apache.mesos.Protos.TaskStatus;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.executor.prod.DaemonTaskScheduler.DaemonJob;
 import org.apache.shardingsphere.elasticjob.cloud.facade.CloudJobFacade;
 import org.apache.shardingsphere.elasticjob.infra.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.script.props.ScriptJobProperties;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutorThreadTest.java b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutorThreadTest.java
index 56936c8..b958696 100755
--- a/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutorThreadTest.java
+++ b/elasticjob-cloud/elasticjob-cloud-executor/src/test/java/org/apache/shardingsphere/elasticjob/cloud/executor/prod/TaskExecutorThreadTest.java
@@ -25,10 +25,10 @@ import org.apache.mesos.Protos.TaskID;
 import org.apache.mesos.Protos.TaskInfo;
 import org.apache.mesos.Protos.TaskState;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.executor.fixture.TestSimpleJob;
 import org.apache.shardingsphere.elasticjob.cloud.executor.prod.TaskExecutor.TaskThread;
 import org.apache.shardingsphere.elasticjob.infra.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.pojo.JobConfigurationPOJO;
 import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
 import org.apache.shardingsphere.elasticjob.script.props.ScriptJobProperties;
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoData.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoData.java
index b39bbf6..b8f2626 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoData.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoData.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos;
 
 import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobConfiguration;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.pojo.JobConfigurationPOJO;
 import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
 
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskLaunchScheduledService.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskLaunchScheduledService.java
index cf4fb87..7fbe548 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskLaunchScheduledService.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskLaunchScheduledService.java
@@ -32,7 +32,6 @@ import org.apache.mesos.Protos;
 import org.apache.mesos.Protos.OfferID;
 import org.apache.mesos.Protos.TaskInfo;
 import org.apache.mesos.SchedulerDriver;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobConfiguration;
 import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
 import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
@@ -43,6 +42,7 @@ import org.apache.shardingsphere.elasticjob.infra.context.ShardingItemParameters
 import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
 import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
 import org.apache.shardingsphere.elasticjob.infra.json.GsonFactory;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.script.props.ScriptJobProperties;
 import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent;
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoDataTest.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoDataTest.java
index a764625..fef9188 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoDataTest.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/mesos/TaskInfoDataTest.java
@@ -18,8 +18,8 @@
 package org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos;
 
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.cloud.scheduler.fixture.CloudJobConfigurationBuilder;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.junit.Test;
 
 import java.util.Collections;
diff --git a/elasticjob-error-handler/elasticjob-error-handler-type/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler b/elasticjob-error-handler/elasticjob-error-handler-type/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler
new file mode 100644
index 0000000..f4c1e74
--- /dev/null
+++ b/elasticjob-error-handler/elasticjob-error-handler-type/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler
@@ -0,0 +1,18 @@
+#
+# 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.error.handler.fixture.LogJobErrorHandler
diff --git a/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java b/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
index 8e7dcf6..b098dde 100644
--- a/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
+++ b/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutor.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.elasticjob.executor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandler;
 import org.apache.shardingsphere.elasticjob.error.handler.JobErrorHandlerFactory;
 import org.apache.shardingsphere.elasticjob.infra.env.IpUtils;
@@ -29,6 +28,7 @@ import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironm
 import org.apache.shardingsphere.elasticjob.infra.handler.threadpool.JobExecutorServiceHandlerFactory;
 import org.apache.shardingsphere.elasticjob.executor.item.JobItemExecutor;
 import org.apache.shardingsphere.elasticjob.executor.item.JobItemExecutorFactory;
+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;
diff --git a/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/JobFacade.java b/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/JobFacade.java
index 6d0c79b..1e89f63 100644
--- a/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/JobFacade.java
+++ b/elasticjob-executor/elasticjob-executor-kernel/src/main/java/org/apache/shardingsphere/elasticjob/executor/JobFacade.java
@@ -18,8 +18,8 @@
 package org.apache.shardingsphere.elasticjob.executor;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobExecutionEvent;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent.State;
 
diff --git a/elasticjob-executor/elasticjob-executor-kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutorTest.java b/elasticjob-executor/elasticjob-executor-kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutorTest.java
index f3d27a4..b328321 100644
--- a/elasticjob-executor/elasticjob-executor-kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutorTest.java
+++ b/elasticjob-executor/elasticjob-executor-kernel/src/test/java/org/apache/shardingsphere/elasticjob/executor/ElasticJobExecutorTest.java
@@ -19,11 +19,11 @@ package org.apache.shardingsphere.elasticjob.executor;
 
 import lombok.SneakyThrows;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.executor.fixture.executor.ClassedFooJobExecutor;
 import org.apache.shardingsphere.elasticjob.executor.fixture.job.FooJob;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent.State;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ElasticJobListener.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
similarity index 86%
rename from elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ElasticJobListener.java
rename to elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
index 93428bd..3086f63 100644
--- a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ElasticJobListener.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
@@ -15,12 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.api.listener;
+package org.apache.shardingsphere.elasticjob.infra.listener;
+
+import org.apache.shardingsphere.elasticjob.infra.spi.TypedSPI;
 
 /**
  * ElasticJob listener.
  */
-public interface ElasticJobListener {
+public interface ElasticJobListener extends TypedSPI {
     
     /**
      * Called before job executed.
diff --git a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
new file mode 100644
index 0000000..97083e6
--- /dev/null
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListenerFactory.java
@@ -0,0 +1,53 @@
+/*
+ * 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 lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * Job listener factory.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ElasticJobListenerFactory {
+    
+    private static final Map<String, ElasticJobListener> HANDLERS = new LinkedHashMap<>();
+    
+    static {
+        for (ElasticJobListener each : ServiceLoader.load(ElasticJobListener.class)) {
+            HANDLERS.put(each.getType(), each);
+        }
+    }
+    
+    /**
+     * Get job listener.
+     *
+     * @param type job listener type
+     * @return job listener
+     */
+    public static ElasticJobListener getListener(final String type) {
+        if (!HANDLERS.containsKey(type)) {
+            throw new IllegalArgumentException(String.format("Can not find job listener type '%s'.", type));
+        }
+        return HANDLERS.get(type);
+    } 
+}
diff --git a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContexts.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContexts.java
similarity index 97%
rename from elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContexts.java
rename to elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContexts.java
index a24cb2c..85ab861 100644
--- a/elasticjob-api/src/main/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContexts.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContexts.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.api.listener;
+package org.apache.shardingsphere.elasticjob.infra.listener;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
diff --git a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJO.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJO.java
index a9ee4c7..8dfd347 100644
--- a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJO.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJO.java
@@ -21,6 +21,8 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Properties;
 
 /**
@@ -56,6 +58,8 @@ public final class JobConfigurationPOJO {
     
     private String jobErrorHandlerType;
     
+    private Collection<String> jobListenerTypes = new ArrayList<>();
+    
     private String description;
     
     private Properties props = new Properties();
@@ -75,7 +79,7 @@ public final class JobConfigurationPOJO {
                 .monitorExecution(monitorExecution).failover(failover).misfire(misfire)
                 .maxTimeDiffSeconds(maxTimeDiffSeconds).reconcileIntervalMinutes(reconcileIntervalMinutes)
                 .jobShardingStrategyType(jobShardingStrategyType).jobExecutorServiceHandlerType(jobExecutorServiceHandlerType).jobErrorHandlerType(jobErrorHandlerType)
-                .description(description).disabled(disabled).overwrite(overwrite).build();
+                .jobListenerTypes(jobListenerTypes.toArray(new String[]{})).description(description).disabled(disabled).overwrite(overwrite).build();
         for (Object each : props.keySet()) {
             result.getProps().setProperty(each.toString(), props.get(each.toString()).toString());
         }
@@ -103,6 +107,7 @@ public final class JobConfigurationPOJO {
         result.setJobShardingStrategyType(jobConfiguration.getJobShardingStrategyType());
         result.setJobExecutorServiceHandlerType(jobConfiguration.getJobExecutorServiceHandlerType());
         result.setJobErrorHandlerType(jobConfiguration.getJobErrorHandlerType());
+        result.setJobListenerTypes(jobConfiguration.getJobListenerTypes());
         result.setDescription(jobConfiguration.getDescription());
         result.setProps(jobConfiguration.getProps());
         result.setDisabled(jobConfiguration.isDisabled());
diff --git a/elasticjob-api/src/test/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContextsTest.java b/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContextsTest.java
similarity index 97%
rename from elasticjob-api/src/test/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContextsTest.java
rename to elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContextsTest.java
index fccddfb..bb0f29b 100644
--- a/elasticjob-api/src/test/java/org/apache/shardingsphere/elasticjob/api/listener/ShardingContextsTest.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/listener/ShardingContextsTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.api.listener;
+package org.apache.shardingsphere.elasticjob.infra.listener;
 
 import org.apache.shardingsphere.elasticjob.api.ShardingContext;
 import org.junit.Test;
diff --git a/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJOTest.java b/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJOTest.java
index 0ed703c..9409fec 100644
--- a/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJOTest.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/test/java/org/apache/shardingsphere/elasticjob/infra/pojo/JobConfigurationPOJOTest.java
@@ -21,6 +21,9 @@ import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
 import org.junit.Test;
 
+import java.util.Arrays;
+
+import static org.hamcrest.CoreMatchers.hasItem;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
@@ -73,6 +76,7 @@ public final class JobConfigurationPOJOTest {
         pojo.setJobShardingStrategyType("AVG_ALLOCATION");
         pojo.setJobExecutorServiceHandlerType("CPU");
         pojo.setJobErrorHandlerType("IGNORE");
+        pojo.setJobListenerTypes(Arrays.asList("LOG"));
         pojo.setDescription("Job description");
         pojo.getProps().setProperty("key", "value");
         pojo.setDisabled(true);
@@ -89,6 +93,7 @@ public final class JobConfigurationPOJOTest {
         assertThat(actual.getJobShardingStrategyType(), is("AVG_ALLOCATION"));
         assertThat(actual.getJobExecutorServiceHandlerType(), is("CPU"));
         assertThat(actual.getJobErrorHandlerType(), is("IGNORE"));
+        assertThat(actual.getJobListenerTypes(), hasItem("LOG"));
         assertThat(actual.getDescription(), is("Job description"));
         assertThat(actual.getProps().getProperty("key"), is("value"));
         assertTrue(actual.isDisabled());
@@ -102,7 +107,7 @@ public final class JobConfigurationPOJOTest {
                 .shardingItemParameters("0=A,1=B,2=C").jobParameter("param")
                 .monitorExecution(true).failover(true).misfire(true)
                 .jobShardingStrategyType("AVG_ALLOCATION").jobExecutorServiceHandlerType("CPU").jobErrorHandlerType("IGNORE")
-                .description("Job description").setProperty("key", "value")
+                .jobListenerTypes("LOG").description("Job description").setProperty("key", "value")
                 .disabled(true).overwrite(true).build();
         JobConfigurationPOJO actual = JobConfigurationPOJO.fromJobConfiguration(jobConfiguration);
         assertThat(actual.getJobName(), is("test_job"));
@@ -116,6 +121,7 @@ public final class JobConfigurationPOJOTest {
         assertThat(actual.getJobShardingStrategyType(), is("AVG_ALLOCATION"));
         assertThat(actual.getJobExecutorServiceHandlerType(), is("CPU"));
         assertThat(actual.getJobErrorHandlerType(), is("IGNORE"));
+        assertThat(actual.getJobListenerTypes(), hasItem("LOG"));
         assertThat(actual.getDescription(), is("Job description"));
         assertThat(actual.getProps().getProperty("key"), is("value"));
         assertTrue(actual.isDisabled());
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/OneOffJobBootstrap.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/OneOffJobBootstrap.java
index 84737c5..32f8a2d 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/OneOffJobBootstrap.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/OneOffJobBootstrap.java
@@ -21,7 +21,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.JobBootstrap;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.lite.internal.instance.InstanceOperation;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodePath;
@@ -36,22 +35,20 @@ public final class OneOffJobBootstrap implements JobBootstrap {
     
     private final JobScheduler jobScheduler;
     
-    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, elasticJobListeners);
+    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig);
     }
     
-    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig,
-                              final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, tracingConfig, elasticJobListeners);
+    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, tracingConfig);
     }
     
-    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, elasticJobListeners);
+    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig);
     }
     
-    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig,
-                              final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, tracingConfig, elasticJobListeners);
+    public OneOffJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, tracingConfig);
     }
     
     /**
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/ScheduleJobBootstrap.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/ScheduleJobBootstrap.java
index 953940f..513d67f 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/ScheduleJobBootstrap.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/bootstrap/impl/ScheduleJobBootstrap.java
@@ -21,7 +21,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.JobBootstrap;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler;
@@ -34,22 +33,20 @@ public final class ScheduleJobBootstrap implements JobBootstrap {
     
     private final JobScheduler jobScheduler;
     
-    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, elasticJobListeners);
+    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig);
     }
     
-    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig,
-                                final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, tracingConfig, elasticJobListeners);
+    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJob, jobConfig, tracingConfig);
     }
     
-    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, elasticJobListeners);
+    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig);
     }
     
-    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig,
-                                final ElasticJobListener... elasticJobListeners) {
-        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, tracingConfig, elasticJobListeners);
+    public ScheduleJobBootstrap(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration tracingConfig) {
+        jobScheduler = new JobScheduler(regCenter, elasticJobType, jobConfig, tracingConfig);
     }
     
     /**
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/listener/AbstractDistributeOnceElasticJobListener.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/listener/AbstractDistributeOnceElasticJobListener.java
index 12e5345..7ef17f8 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/listener/AbstractDistributeOnceElasticJobListener.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/api/listener/AbstractDistributeOnceElasticJobListener.java
@@ -18,11 +18,11 @@
 package org.apache.shardingsphere.elasticjob.lite.api.listener;
 
 import lombok.Setter;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.concurrent.BlockUtils;
 import org.apache.shardingsphere.elasticjob.infra.env.TimeService;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.guarantee.GuaranteeService;
 
 import java.util.Set;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManager.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManager.java
index a847f0d..7497592 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManager.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManager.java
@@ -17,13 +17,13 @@
 
 package org.apache.shardingsphere.elasticjob.lite.internal.guarantee;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.listener.AbstractJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.listener.AbstractListenerManager;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 
-import java.util.List;
+import java.util.Collection;
 
 /**
  * Guarantee listener manager.
@@ -32,9 +32,9 @@ public final class GuaranteeListenerManager extends AbstractListenerManager {
     
     private final GuaranteeNode guaranteeNode;
     
-    private final List<ElasticJobListener> elasticJobListeners;
+    private final Collection<ElasticJobListener> elasticJobListeners;
     
-    public GuaranteeListenerManager(final CoordinatorRegistryCenter regCenter, final String jobName, final List<ElasticJobListener> elasticJobListeners) {
+    public GuaranteeListenerManager(final CoordinatorRegistryCenter regCenter, final String jobName, final Collection<ElasticJobListener> elasticJobListeners) {
         super(regCenter, jobName);
         this.guaranteeNode = new GuaranteeNode(jobName);
         this.elasticJobListeners = elasticJobListeners;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/listener/ListenerManager.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/listener/ListenerManager.java
index b857eb6..2452029 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/listener/ListenerManager.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/listener/ListenerManager.java
@@ -17,7 +17,7 @@
 
 package org.apache.shardingsphere.elasticjob.lite.internal.listener;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.RescheduleListenerManager;
 import org.apache.shardingsphere.elasticjob.lite.internal.election.ElectionListenerManager;
 import org.apache.shardingsphere.elasticjob.lite.internal.failover.FailoverListenerManager;
@@ -29,7 +29,7 @@ import org.apache.shardingsphere.elasticjob.lite.internal.sharding.ShardingListe
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 
-import java.util.List;
+import java.util.Collection;
 
 /**
  * Listener manager facade.
@@ -56,7 +56,7 @@ public final class ListenerManager {
     
     private final RegistryCenterConnectionStateListener regCenterConnectionStateListener;
     
-    public ListenerManager(final CoordinatorRegistryCenter regCenter, final String jobName, final List<ElasticJobListener> elasticJobListeners) {
+    public ListenerManager(final CoordinatorRegistryCenter regCenter, final String jobName, final Collection<ElasticJobListener> elasticJobListeners) {
         jobNodeStorage = new JobNodeStorage(regCenter, jobName);
         electionListenerManager = new ElectionListenerManager(regCenter, jobName);
         shardingListenerManager = new ShardingListenerManager(regCenter, jobName);
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/JobScheduler.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/JobScheduler.java
index 89575e9..ab52c6c 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/JobScheduler.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/JobScheduler.java
@@ -20,10 +20,11 @@ package org.apache.shardingsphere.elasticjob.lite.internal.schedule;
 import lombok.Getter;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
 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.lite.api.listener.AbstractDistributeOnceElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.guarantee.GuaranteeService;
 import org.apache.shardingsphere.elasticjob.lite.internal.setup.JobClassNameProviderFactory;
@@ -37,9 +38,9 @@ import org.quartz.SchedulerException;
 import org.quartz.impl.StdSchedulerFactory;
 import org.quartz.simpl.SimpleThreadPool;
 
-import java.util.Arrays;
-import java.util.List;
+import java.util.Collection;
 import java.util.Properties;
+import java.util.stream.Collectors;
 
 /**
  * Job scheduler.
@@ -51,15 +52,11 @@ public final class JobScheduler {
     @Getter
     private final CoordinatorRegistryCenter regCenter;
     
-    private final ElasticJob elasticJob;
-    
     private final String elasticJobType;
     
     @Getter
     private final JobConfiguration jobConfig;
     
-    private final List<ElasticJobListener> elasticJobListeners;
-    
     private final SetUpFacade setUpFacade;
     
     private final SchedulerFacade schedulerFacade;
@@ -71,46 +68,44 @@ public final class JobScheduler {
     @Getter
     private final JobScheduleController jobScheduleController;
     
-    public JobScheduler(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        this(regCenter, elasticJob, jobConfig, null, elasticJobListeners);
+    public JobScheduler(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig) {
+        this(regCenter, elasticJob, jobConfig, null);
     }
     
-    public JobScheduler(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration<?> tracingConfig,
-                        final ElasticJobListener... elasticJobListeners) {
+    public JobScheduler(final CoordinatorRegistryCenter regCenter, final ElasticJob elasticJob, final JobConfiguration jobConfig, final TracingConfiguration<?> tracingConfig) {
         this.regCenter = regCenter;
-        this.elasticJob = elasticJob;
         elasticJobType = null;
-        this.elasticJobListeners = Arrays.asList(elasticJobListeners);
-        setUpFacade = new SetUpFacade(regCenter, jobConfig.getJobName(), this.elasticJobListeners);
+        final Collection<ElasticJobListener> elasticJobListeners = jobConfig.getJobListenerTypes().stream()
+                .map(ElasticJobListenerFactory::getListener).collect(Collectors.toList());
+        setUpFacade = new SetUpFacade(regCenter, jobConfig.getJobName(), elasticJobListeners);
         schedulerFacade = new SchedulerFacade(regCenter, jobConfig.getJobName());
-        jobFacade = new LiteJobFacade(regCenter, jobConfig.getJobName(), this.elasticJobListeners, tracingConfig);
+        jobFacade = new LiteJobFacade(regCenter, jobConfig.getJobName(), elasticJobListeners, tracingConfig);
         jobExecutor = null == elasticJob ? new ElasticJobExecutor(elasticJobType, jobConfig, jobFacade) : new ElasticJobExecutor(elasticJob, jobConfig, jobFacade);
         String jobClassName = JobClassNameProviderFactory.getProvider().getJobClassName(elasticJob);
         this.jobConfig = setUpFacade.setUpJobConfiguration(jobClassName, jobConfig);
-        setGuaranteeServiceForElasticJobListeners(regCenter, this.elasticJobListeners);
+        setGuaranteeServiceForElasticJobListeners(regCenter, elasticJobListeners);
         jobScheduleController = createJobScheduleController();
     }
     
-    public JobScheduler(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final ElasticJobListener... elasticJobListeners) {
-        this(regCenter, elasticJobType, jobConfig, null, elasticJobListeners);
+    public JobScheduler(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig) {
+        this(regCenter, elasticJobType, jobConfig, null);
     }
     
-    public JobScheduler(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration<?> tracingConfig,
-                        final ElasticJobListener... elasticJobListeners) {
+    public JobScheduler(final CoordinatorRegistryCenter regCenter, final String elasticJobType, final JobConfiguration jobConfig, final TracingConfiguration<?> tracingConfig) {
         this.regCenter = regCenter;
-        elasticJob = null;
         this.elasticJobType = elasticJobType;
-        this.elasticJobListeners = Arrays.asList(elasticJobListeners);
-        setUpFacade = new SetUpFacade(regCenter, jobConfig.getJobName(), this.elasticJobListeners);
+        final Collection<ElasticJobListener> elasticJobListeners = jobConfig.getJobListenerTypes().stream()
+                .map(ElasticJobListenerFactory::getListener).collect(Collectors.toList());
+        setUpFacade = new SetUpFacade(regCenter, jobConfig.getJobName(), elasticJobListeners);
         schedulerFacade = new SchedulerFacade(regCenter, jobConfig.getJobName());
-        jobFacade = new LiteJobFacade(regCenter, jobConfig.getJobName(), this.elasticJobListeners, tracingConfig);
+        jobFacade = new LiteJobFacade(regCenter, jobConfig.getJobName(), elasticJobListeners, tracingConfig);
         jobExecutor = new ElasticJobExecutor(elasticJobType, jobConfig, jobFacade);
         this.jobConfig = setUpFacade.setUpJobConfiguration(elasticJobType, jobConfig);
-        setGuaranteeServiceForElasticJobListeners(regCenter, this.elasticJobListeners);
+        setGuaranteeServiceForElasticJobListeners(regCenter, elasticJobListeners);
         jobScheduleController = createJobScheduleController();
     }
     
-    private void setGuaranteeServiceForElasticJobListeners(final CoordinatorRegistryCenter regCenter, final List<ElasticJobListener> elasticJobListeners) {
+    private void setGuaranteeServiceForElasticJobListeners(final CoordinatorRegistryCenter regCenter, final Collection<ElasticJobListener> elasticJobListeners) {
         GuaranteeService guaranteeService = new GuaranteeService(regCenter, jobConfig.getJobName());
         for (ElasticJobListener each : elasticJobListeners) {
             if (each instanceof AbstractDistributeOnceElasticJobListener) {
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacade.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacade.java
index 23067b5..ad6fa88 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacade.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacade.java
@@ -20,11 +20,11 @@ package org.apache.shardingsphere.elasticjob.lite.internal.schedule;
 import com.google.common.base.Strings;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.executor.JobFacade;
 import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.failover.FailoverService;
 import org.apache.shardingsphere.elasticjob.lite.internal.sharding.ExecutionContextService;
@@ -57,11 +57,11 @@ public final class LiteJobFacade implements JobFacade {
     
     private final FailoverService failoverService;
     
-    private final List<ElasticJobListener> elasticJobListeners;
+    private final Collection<ElasticJobListener> elasticJobListeners;
     
     private final JobEventBus jobEventBus;
     
-    public LiteJobFacade(final CoordinatorRegistryCenter regCenter, final String jobName, final List<ElasticJobListener> elasticJobListeners, final TracingConfiguration tracingConfig) {
+    public LiteJobFacade(final CoordinatorRegistryCenter regCenter, final String jobName, final Collection<ElasticJobListener> elasticJobListeners, final TracingConfiguration tracingConfig) {
         configService = new ConfigurationService(regCenter, jobName);
         shardingService = new ShardingService(regCenter, jobName);
         executionContextService = new ExecutionContextService(regCenter, jobName);
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/setup/SetUpFacade.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/setup/SetUpFacade.java
index 97b5263..34f37bd 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/setup/SetUpFacade.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/setup/SetUpFacade.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.lite.internal.setup;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.election.LeaderService;
 import org.apache.shardingsphere.elasticjob.lite.internal.instance.InstanceService;
@@ -27,7 +27,7 @@ import org.apache.shardingsphere.elasticjob.lite.internal.reconcile.ReconcileSer
 import org.apache.shardingsphere.elasticjob.lite.internal.server.ServerService;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 
-import java.util.List;
+import java.util.Collection;
 
 /**
  * Set up facade.
@@ -46,7 +46,7 @@ public final class SetUpFacade {
     
     private final ListenerManager listenerManager;
     
-    public SetUpFacade(final CoordinatorRegistryCenter regCenter, final String jobName, final List<ElasticJobListener> elasticJobListeners) {
+    public SetUpFacade(final CoordinatorRegistryCenter regCenter, final String jobName, final Collection<ElasticJobListener> elasticJobListeners) {
         configService = new ConfigurationService(regCenter, jobName);
         leaderService = new LeaderService(regCenter, jobName);
         serverService = new ServerService(regCenter, jobName);
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextService.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextService.java
index 003db89..866ddca 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextService.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextService.java
@@ -18,9 +18,9 @@
 package org.apache.shardingsphere.elasticjob.lite.internal.sharding;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.context.ShardingItemParameters;
 import org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobInstance;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobRegistry;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionService.java b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionService.java
index de8a711..7bafdc0 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionService.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/main/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionService.java
@@ -18,7 +18,7 @@
 package org.apache.shardingsphere.elasticjob.lite.internal.sharding;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobRegistry;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/DistributeOnceElasticJobListenerTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/DistributeOnceElasticJobListenerTest.java
index c40b105..549daef 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/DistributeOnceElasticJobListenerTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/DistributeOnceElasticJobListenerTest.java
@@ -18,10 +18,10 @@
 package org.apache.shardingsphere.elasticjob.lite.api.listener;
 
 import com.google.common.collect.Sets;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.fixture.ElasticJobListenerCaller;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.fixture.TestDistributeOnceElasticJobListener;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.guarantee.GuaranteeService;
 import org.apache.shardingsphere.elasticjob.lite.util.ReflectionUtils;
 import org.apache.shardingsphere.elasticjob.infra.env.TimeService;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java
index 8852f7e..6150d65 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java
@@ -17,13 +17,17 @@
 
 package org.apache.shardingsphere.elasticjob.lite.api.listener.fixture;
 
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 
 public final class TestDistributeOnceElasticJobListener extends AbstractDistributeOnceElasticJobListener {
     
     private final ElasticJobListenerCaller caller;
     
+    public TestDistributeOnceElasticJobListener() {
+        this(null);
+    }
+    
     public TestDistributeOnceElasticJobListener(final ElasticJobListenerCaller caller) {
         super(1L, 1L);
         this.caller = caller;
@@ -38,4 +42,9 @@ public final class TestDistributeOnceElasticJobListener extends AbstractDistribu
     public void doAfterJobExecutedAtLastCompleted(final ShardingContexts shardingContexts) {
         caller.after();
     }
+    
+    @Override
+    public String getType() {
+        return "DISTRIBUTE";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java
index fa1a710..016f296 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java
@@ -18,14 +18,18 @@
 package org.apache.shardingsphere.elasticjob.lite.api.listener.fixture;
 
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 
 @RequiredArgsConstructor
 public final class TestElasticJobListener implements ElasticJobListener {
     
     private final ElasticJobListenerCaller caller;
     
+    public TestElasticJobListener() {
+        this(null);
+    }
+    
     @Override
     public void beforeJobExecuted(final ShardingContexts shardingContexts) {
         caller.before();
@@ -35,4 +39,9 @@ public final class TestElasticJobListener implements ElasticJobListener {
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
         caller.after();
     }
+    
+    @Override
+    public String getType() {
+        return "TEST";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/BaseIntegrateTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/BaseIntegrateTest.java
index a00e1fe..9eb6b81 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/BaseIntegrateTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/BaseIntegrateTest.java
@@ -24,9 +24,6 @@ import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.OneOffJobBoo
 import org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap;
 import org.apache.shardingsphere.elasticjob.api.ElasticJob;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.fixture.EmbedTestingServer;
 import org.apache.shardingsphere.elasticjob.lite.internal.election.LeaderService;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobRegistry;
@@ -56,6 +53,10 @@ public abstract class BaseIntegrateTest {
     
     private final String jobName = System.nanoTime() + "_test_job";
     
+    protected BaseIntegrateTest() {
+        this(null, null);
+    }
+    
     protected BaseIntegrateTest(final TestType type, final ElasticJob elasticJob) {
         this.elasticJob = elasticJob;
         jobConfiguration = getJobConfiguration(jobName);
@@ -68,9 +69,9 @@ public abstract class BaseIntegrateTest {
     private JobBootstrap createJobBootstrap(final TestType type, final ElasticJob elasticJob) {
         switch (type) {
             case SCHEDULE:
-                return new ScheduleJobBootstrap(REGISTRY_CENTER, elasticJob, jobConfiguration, new TestElasticJobListener(), new TestDistributeOnceElasticJobListener());
+                return new ScheduleJobBootstrap(REGISTRY_CENTER, elasticJob, jobConfiguration);
             case ONE_OFF:
-                return new OneOffJobBootstrap(REGISTRY_CENTER, elasticJob, jobConfiguration, new TestElasticJobListener(), new TestDistributeOnceElasticJobListener());
+                return new OneOffJobBootstrap(REGISTRY_CENTER, elasticJob, jobConfiguration);
             default:
                 throw new RuntimeException(String.format("Cannot support `%s`", type));
         }
@@ -102,32 +103,4 @@ public abstract class BaseIntegrateTest {
         
         SCHEDULE, ONE_OFF
     }
-    
-    private final class TestElasticJobListener implements ElasticJobListener {
-        
-        @Override
-        public void beforeJobExecuted(final ShardingContexts shardingContexts) {
-            REGISTRY_CENTER.persist("/" + jobName + "/listener/every", "test");
-        }
-        
-        @Override
-        public void afterJobExecuted(final ShardingContexts shardingContexts) {
-        }
-    }
-    
-    private final class TestDistributeOnceElasticJobListener extends AbstractDistributeOnceElasticJobListener {
-    
-        private TestDistributeOnceElasticJobListener() {
-            super(100L, 100L);
-        }
-        
-        @Override
-        public void doBeforeJobExecutedAtLastStarted(final ShardingContexts shardingContexts) {
-            REGISTRY_CENTER.persist("/" + jobName + "/listener/once", "test");
-        }
-    
-        @Override
-        public void doAfterJobExecutedAtLastCompleted(final ShardingContexts shardingContexts) {
-        }
-    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/OneOffDisabledJobIntegrateTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/OneOffDisabledJobIntegrateTest.java
index 876f3bd..77665b1 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/OneOffDisabledJobIntegrateTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/OneOffDisabledJobIntegrateTest.java
@@ -29,7 +29,8 @@ public final class OneOffDisabledJobIntegrateTest extends DisabledJobIntegrateTe
     
     @Override
     protected JobConfiguration getJobConfiguration(final String jobName) {
-        return JobConfiguration.newBuilder(jobName, 3).shardingItemParameters("0=A,1=B,2=C").disabled(true).overwrite(true).build();
+        return JobConfiguration.newBuilder(jobName, 3).shardingItemParameters("0=A,1=B,2=C")
+                .jobListenerTypes("INTEGRATE-TEST", "INTEGRATE-DISTRIBUTE").disabled(true).overwrite(true).build();
     }
     
     @Test
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/ScheduleDisabledJobIntegrateTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/ScheduleDisabledJobIntegrateTest.java
index e362194..36effec 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/ScheduleDisabledJobIntegrateTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/disable/ScheduleDisabledJobIntegrateTest.java
@@ -34,7 +34,8 @@ public final class ScheduleDisabledJobIntegrateTest extends DisabledJobIntegrate
     
     @Override
     protected JobConfiguration getJobConfiguration(final String jobName) {
-        return JobConfiguration.newBuilder(jobName, 3).cron("0/1 * * * * ?").shardingItemParameters("0=A,1=B,2=C").disabled(true).overwrite(true).build();
+        return JobConfiguration.newBuilder(jobName, 3).cron("0/1 * * * * ?").shardingItemParameters("0=A,1=B,2=C")
+                .jobListenerTypes("INTEGRATE-TEST", "INTEGRATE-DISTRIBUTE").disabled(true).overwrite(true).build();
     }
     
     @Test
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/OneOffEnabledJobIntegrateTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/OneOffEnabledJobIntegrateTest.java
index 016c254..2bcfedc 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/OneOffEnabledJobIntegrateTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/OneOffEnabledJobIntegrateTest.java
@@ -32,7 +32,8 @@ public final class OneOffEnabledJobIntegrateTest extends EnabledJobIntegrateTest
     
     @Override
     protected JobConfiguration getJobConfiguration(final String jobName) {
-        return JobConfiguration.newBuilder(jobName, 3).shardingItemParameters("0=A,1=B,2=C").overwrite(true).build();
+        return JobConfiguration.newBuilder(jobName, 3).shardingItemParameters("0=A,1=B,2=C")
+                .jobListenerTypes("INTEGRATE-TEST", "INTEGRATE-DISTRIBUTE").overwrite(true).build();
     }
     
     @Test
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/ScheduleEnabledJobIntegrateTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/ScheduleEnabledJobIntegrateTest.java
index c6c42ca..5ce9bf7 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/ScheduleEnabledJobIntegrateTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/enable/ScheduleEnabledJobIntegrateTest.java
@@ -32,7 +32,8 @@ public final class ScheduleEnabledJobIntegrateTest extends EnabledJobIntegrateTe
     
     @Override
     protected JobConfiguration getJobConfiguration(final String jobName) {
-        return JobConfiguration.newBuilder(jobName, 3).cron("0/1 * * * * ?").shardingItemParameters("0=A,1=B,2=C").overwrite(true).build();
+        return JobConfiguration.newBuilder(jobName, 3).cron("0/1 * * * * ?").shardingItemParameters("0=A,1=B,2=C")
+                .jobListenerTypes("INTEGRATE-TEST", "INTEGRATE-DISTRIBUTE").overwrite(true).build();
     }
     
     @Test
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestDistributeOnceElasticJobListener.java
similarity index 70%
copy from elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java
copy to elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestDistributeOnceElasticJobListener.java
index 8852f7e..5bcb7f8 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestDistributeOnceElasticJobListener.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestDistributeOnceElasticJobListener.java
@@ -15,27 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.lite.api.listener.fixture;
+package org.apache.shardingsphere.elasticjob.lite.integrate.listener;
 
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 
-public final class TestDistributeOnceElasticJobListener extends AbstractDistributeOnceElasticJobListener {
+public class TestDistributeOnceElasticJobListener extends AbstractDistributeOnceElasticJobListener {
     
-    private final ElasticJobListenerCaller caller;
-    
-    public TestDistributeOnceElasticJobListener(final ElasticJobListenerCaller caller) {
-        super(1L, 1L);
-        this.caller = caller;
+    public TestDistributeOnceElasticJobListener() {
+        super(100L, 100L);
     }
     
     @Override
     public void doBeforeJobExecutedAtLastStarted(final ShardingContexts shardingContexts) {
-        caller.before();
     }
     
     @Override
     public void doAfterJobExecutedAtLastCompleted(final ShardingContexts shardingContexts) {
-        caller.after();
+    }
+    
+    @Override
+    public String getType() {
+        return "INTEGRATE-DISTRIBUTE";
     }
 }
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestElasticJobListener.java
similarity index 68%
copy from elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java
copy to elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestElasticJobListener.java
index fa1a710..3b24daf 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/api/listener/fixture/TestElasticJobListener.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/integrate/listener/TestElasticJobListener.java
@@ -15,24 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.elasticjob.lite.api.listener.fixture;
+package org.apache.shardingsphere.elasticjob.lite.integrate.listener;
 
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 
-@RequiredArgsConstructor
-public final class TestElasticJobListener implements ElasticJobListener {
-    
-    private final ElasticJobListenerCaller caller;
+public class TestElasticJobListener implements ElasticJobListener {
     
     @Override
     public void beforeJobExecuted(final ShardingContexts shardingContexts) {
-        caller.before();
     }
     
     @Override
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
-        caller.after();
+    }
+    
+    @Override
+    public String getType() {
+        return "INTEGRATE-TEST";
     }
 }
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManagerTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManagerTest.java
index 2007a13..ca2be42 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManagerTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/guarantee/GuaranteeListenerManagerTest.java
@@ -18,8 +18,8 @@
 package org.apache.shardingsphere.elasticjob.lite.internal.guarantee;
 
 import org.apache.curator.framework.recipes.cache.CuratorCacheListener.Type;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.listener.AbstractJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
 import org.apache.shardingsphere.elasticjob.lite.util.ReflectionUtils;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacadeTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacadeTest.java
index 1642ab6..9aedf95 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacadeTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/schedule/LiteJobFacadeTest.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.elasticjob.lite.internal.schedule;
 
 import com.google.common.collect.Lists;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.exception.JobExecutionEnvironmentException;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.fixture.ElasticJobListenerCaller;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.fixture.TestElasticJobListener;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextServiceTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextServiceTest.java
index 9726593..77d04ea 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextServiceTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionContextServiceTest.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.elasticjob.lite.internal.sharding;
 
 import com.google.common.collect.Lists;
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobInstance;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobRegistry;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionServiceTest.java b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionServiceTest.java
index defe681..dddaaed 100644
--- a/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionServiceTest.java
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/java/org/apache/shardingsphere/elasticjob/lite/internal/sharding/ExecutionServiceTest.java
@@ -18,7 +18,7 @@
 package org.apache.shardingsphere.elasticjob.lite.internal.sharding;
 
 import org.apache.shardingsphere.elasticjob.api.JobConfiguration;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService;
 import org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobRegistry;
 import org.apache.shardingsphere.elasticjob.lite.internal.storage.JobNodeStorage;
diff --git a/elasticjob-lite/elasticjob-lite-core/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener b/elasticjob-lite/elasticjob-lite-core/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener
new file mode 100644
index 0000000..85a5465
--- /dev/null
+++ b/elasticjob-lite/elasticjob-lite-core/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener
@@ -0,0 +1,21 @@
+#
+# 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.lite.api.listener.fixture.TestDistributeOnceElasticJobListener
+org.apache.shardingsphere.elasticjob.lite.api.listener.fixture.TestElasticJobListener
+org.apache.shardingsphere.elasticjob.lite.integrate.listener.TestDistributeOnceElasticJobListener
+org.apache.shardingsphere.elasticjob.lite.integrate.listener.TestElasticJobListener
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/parser/JobBeanDefinitionParser.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/parser/JobBeanDefinitionParser.java
index 5d9da40..5360e20 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/parser/JobBeanDefinitionParser.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/parser/JobBeanDefinitionParser.java
@@ -29,9 +29,12 @@ 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.xml.DomUtils;
 import org.w3c.dom.Element;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
 
@@ -61,7 +64,6 @@ public final class JobBeanDefinitionParser extends AbstractBeanDefinitionParser
         if (!Strings.isNullOrEmpty(tracingRef)) {
             factory.addConstructorArgReference(tracingRef);
         }
-        factory.addConstructorArgValue(createJobListeners(element));
         return factory.getBeanDefinition();
     }
     
@@ -80,6 +82,11 @@ public final class JobBeanDefinitionParser extends AbstractBeanDefinitionParser
         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(Collections.emptyList());
+        } else {
+            result.addConstructorArgValue(Arrays.asList(element.getAttribute(JobBeanDefinitionTag.JOB_LISTENER_TYPES_ATTRIBUTE).split(",")));
+        }
         result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.DESCRIPTION_ATTRIBUTE));
         result.addConstructorArgValue(parsePropsElement(element, parserContext));
         result.addConstructorArgValue(element.getAttribute(JobBeanDefinitionTag.DISABLED_ATTRIBUTE));
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/tag/JobBeanDefinitionTag.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/tag/JobBeanDefinitionTag.java
index 96cc6d2..6001029 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/tag/JobBeanDefinitionTag.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/job/tag/JobBeanDefinitionTag.java
@@ -58,6 +58,8 @@ public final class JobBeanDefinitionTag {
     
     public static final String JOB_ERROR_HANDLER_TYPE_ATTRIBUTE = "job-error-handler-type";
     
+    public static final String JOB_LISTENER_TYPES_ATTRIBUTE = "job-listener-types";
+    
     public static final String DESCRIPTION_ATTRIBUTE = "description";
     
     public static final String PROPS_TAG = "props";
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/resources/META-INF/namespace/elasticjob.xsd b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/resources/META-INF/namespace/elasticjob.xsd
index d42c23b..b61f075 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/resources/META-INF/namespace/elasticjob.xsd
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/main/resources/META-INF/namespace/elasticjob.xsd
@@ -24,27 +24,12 @@
 
     <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd" />
     
-    <xsd:element name="listener">
-        <xsd:complexType>
-            <xsd:attribute name="class" type="xsd:string" use="required" />
-        </xsd:complexType>
-    </xsd:element>
-    <xsd:element name="distributed-listener">
-        <xsd:complexType>
-            <xsd:attribute name="class" type="xsd:string" use="required" />
-            <xsd:attribute name="started-timeout-milliseconds" type="xsd:string" use="required" />
-            <xsd:attribute name="completed-timeout-milliseconds" type="xsd:string" use="required" />
-        </xsd:complexType>
-    </xsd:element>
-    
     <xsd:element name="job">
         <xsd:complexType>
             <xsd:complexContent>
                 <xsd:extension base="beans:identifiedType">
                     <xsd:all>
                         <xsd:element ref="beans:props" minOccurs="0" />
-                        <xsd:element ref="listener" minOccurs="0" />
-                        <xsd:element ref="distributed-listener" minOccurs="0" />
                     </xsd:all>
                     <xsd:attribute name="job-ref" type="xsd:string" />
                     <xsd:attribute name="job-type" type="xsd:string" />
@@ -62,6 +47,7 @@
                     <xsd:attribute name="job-sharding-strategy-type" type="xsd:string" />
                     <xsd:attribute name="job-executor-service-handler-type" type="xsd:string" />
                     <xsd:attribute name="job-error-handler-type" type="xsd:string" />
+                    <xsd:attribute name="job-listener-types" type="xsd:string" />
                     <xsd:attribute name="description" type="xsd:string" />
                     <xsd:attribute name="disabled" type="xsd:string" default="false" />
                     <xsd:attribute name="overwrite" type="xsd:string" default="false" />
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleCglibListener.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleCglibListener.java
index f69bc84..de63269 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleCglibListener.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleCglibListener.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -34,4 +34,9 @@ public class SimpleCglibListener implements ElasticJobListener {
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
         assertThat(shardingContexts.getJobName(), is("simpleElasticJob_namespace_listener_cglib"));
     }
+    
+    @Override
+    public String getType() {
+        return "simpleCglibListener";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleJdkDynamicProxyListener.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleJdkDynamicProxyListener.java
index b1bb087..fe883e1 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleJdkDynamicProxyListener.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleJdkDynamicProxyListener.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -34,4 +34,9 @@ public class SimpleJdkDynamicProxyListener implements ElasticJobListener {
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
         assertThat(shardingContexts.getJobName(), is("simpleElasticJob_namespace_listener_jdk_proxy"));
     }
+    
+    @Override
+    public String getType() {
+        return "simpleJdkDynamicProxyListener";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleListener.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleListener.java
index 8261699..1d3b865 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleListener.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleListener.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener;
 
-import org.apache.shardingsphere.elasticjob.api.listener.ElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener;
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -34,4 +34,9 @@ public class SimpleListener implements ElasticJobListener {
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
         assertThat(shardingContexts.getJobName(), is("simpleElasticJob_namespace_listener"));
     }
+    
+    @Override
+    public String getType() {
+        return "simpleListener";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleOnceListener.java b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleOnceListener.java
index 92308e9..b7dc213 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleOnceListener.java
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/java/org/apache/shardingsphere/elasticjob/lite/spring/namespace/fixture/listener/SimpleOnceListener.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener;
 
+import org.apache.shardingsphere.elasticjob.infra.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.api.listener.AbstractDistributeOnceElasticJobListener;
-import org.apache.shardingsphere.elasticjob.api.listener.ShardingContexts;
 import org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.service.FooService;
 
 import javax.annotation.Resource;
@@ -35,6 +35,10 @@ public class SimpleOnceListener extends AbstractDistributeOnceElasticJobListener
     
     private final long completedTimeoutMilliseconds;
     
+    public SimpleOnceListener() {
+        this(10000, 20000);
+    }
+    
     public SimpleOnceListener(final long startedTimeoutMilliseconds, final long completedTimeoutMilliseconds) {
         super(startedTimeoutMilliseconds, completedTimeoutMilliseconds);
         this.startedTimeoutMilliseconds = startedTimeoutMilliseconds;
@@ -51,4 +55,9 @@ public class SimpleOnceListener extends AbstractDistributeOnceElasticJobListener
     public void doAfterJobExecutedAtLastCompleted(final ShardingContexts shardingContexts) {
         assertThat(completedTimeoutMilliseconds, is(20000L));
     }
+    
+    @Override
+    public String getType() {
+        return "simpleOnceListener";
+    }
 }
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListener.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListener.xml
index c1bc44d..1ed98e0 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListener.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListener.xml
@@ -31,9 +31,7 @@
     
     <elasticjob:job id="simpleElasticJob_namespace_listener" job-ref="fooJob" registry-center-ref="regCenter"
              sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}"
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleListener" />
-        <elasticjob:distributed-listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleOnceListener" started-timeout-milliseconds="10000" completed-timeout-milliseconds="20000" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleListener,simpleOnceListener">
     </elasticjob:job>
     
     <elasticjob:job id="dataflowElasticJob_namespace_listener" job-ref="dataflowJob" registry-center-ref="regCenter"
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndCglib.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndCglib.xml
index 01f529e..6d6e463 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndCglib.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndCglib.xml
@@ -40,8 +40,7 @@
     
     <elasticjob:job id="simpleElasticJob_namespace_listener_cglib" job-ref="fooJob" registry-center-ref="regCenter" tracing-ref="elasticJobTrace" 
              sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}"
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleCglibListener" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleCglibListener">
     </elasticjob:job>
     <elasticjob:job id="dataflowElasticJob_namespace_listener_cglib" job-ref="dataflowJob" registry-center-ref="regCenter" 
              sharding-total-count="3" sharding-item-parameters="0=A,1=B,2=C" description="中文描述"
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndJdkDynamicProxy.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndJdkDynamicProxy.xml
index a788fdd..aa18b90 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndJdkDynamicProxy.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/oneOffWithListenerAndJdkDynamicProxy.xml
@@ -40,8 +40,7 @@
     
     <elasticjob:job id="simpleElasticJob_namespace_listener_jdk_proxy" job-ref="fooJob" registry-center-ref="regCenter" tracing-ref="elasticJobTrace" 
              sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}"
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleJdkDynamicProxyListener" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleJdkDynamicProxyListener">
     </elasticjob:job>
     <elasticjob:job id="dataflowElasticJob_namespace_listener_jdk_proxy" job-ref="dataflowJob" registry-center-ref="regCenter" 
              sharding-total-count="3" sharding-item-parameters="0=A,1=B,2=C" description="中文描述"
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListener.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListener.xml
index 6d2e22b..7e90891 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListener.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListener.xml
@@ -31,9 +31,7 @@
     
     <elasticjob:job id="${simpleJob.id}" job-ref="fooJob" registry-center-ref="regCenter" 
              cron="${simpleJob.cron}" sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}" 
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleListener" />
-        <elasticjob:distributed-listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleOnceListener" started-timeout-milliseconds="10000" completed-timeout-milliseconds="20000" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleListener,simpleOnceListener">
     </elasticjob:job>
     
     <elasticjob:job id="dataflowElasticJob_namespace_listener" job-ref="dataflowJob" registry-center-ref="regCenter" 
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndCglib.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndCglib.xml
index d50a9d2..9cd484e 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndCglib.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndCglib.xml
@@ -40,8 +40,7 @@
     
     <elasticjob:job id="simpleElasticJob_namespace_listener_cglib" job-ref="fooJob" registry-center-ref="regCenter" tracing-ref="elasticJobTrace" 
              cron="${simpleJob.cron}" sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}" 
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleCglibListener" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleCglibListener">
     </elasticjob:job>
     <elasticjob:job id="dataflowElasticJob_namespace_listener_cglib" job-ref="dataflowJob" registry-center-ref="regCenter" 
              cron="0/1 * * * * ?" sharding-total-count="3" sharding-item-parameters="0=A,1=B,2=C" description="中文描述" 
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndJdkDynamicProxy.xml b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndJdkDynamicProxy.xml
index 90101cd..ce1f3fa 100644
--- a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndJdkDynamicProxy.xml
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/job/withListenerAndJdkDynamicProxy.xml
@@ -40,8 +40,7 @@
     
     <elasticjob:job id="simpleElasticJob_namespace_listener_jdk_proxy" job-ref="fooJob" registry-center-ref="regCenter" tracing-ref="elasticJobTrace" 
              cron="${simpleJob.cron}" sharding-total-count="${simpleJob.shardingTotalCount}" sharding-item-parameters="${simpleJob.shardingItemParameters}" 
-             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}">
-        <elasticjob:listener class="org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleJdkDynamicProxyListener" />
+             disabled="${simpleJob.disabled}" overwrite="${simpleJob.overwrite}" job-listener-types="simpleJdkDynamicProxyListener">
     </elasticjob:job>
     <elasticjob:job id="dataflowElasticJob_namespace_listener_jdk_proxy" job-ref="dataflowJob" registry-center-ref="regCenter" 
              cron="0/1 * * * * ?" sharding-total-count="3" sharding-item-parameters="0=A,1=B,2=C" description="中文描述" 
diff --git a/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener
new file mode 100644
index 0000000..c8c5667
--- /dev/null
+++ b/elasticjob-lite/elasticjob-lite-spring/elasticjob-lite-spring-namespace/src/test/resources/META-INF/services/org.apache.shardingsphere.elasticjob.infra.listener.ElasticJobListener
@@ -0,0 +1,21 @@
+#
+# 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.lite.spring.namespace.fixture.listener.SimpleCglibListener
+org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleJdkDynamicProxyListener
+org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleListener
+org.apache.shardingsphere.elasticjob.lite.spring.namespace.fixture.listener.SimpleOnceListener