Support for listener order (#1937) (#1943)

diff --git a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
index 3086f63..f16e784 100644
--- a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/listener/ElasticJobListener.java
@@ -23,6 +23,8 @@
  * ElasticJob listener.
  */
 public interface ElasticJobListener extends TypedSPI {
+
+    int LOWEST = Integer.MAX_VALUE;
     
     /**
      * Called before job executed.
@@ -37,4 +39,12 @@
      * @param shardingContexts sharding contexts
      */
     void afterJobExecuted(ShardingContexts shardingContexts);
+
+    /**
+     * Listener order, default is the lowest.
+     * @return order
+     */
+    default int order() {
+        return LOWEST;
+    }
 }
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 e9b1744..59d0364 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
@@ -39,7 +39,9 @@
 import org.apache.shardingsphere.elasticjob.tracing.event.JobStatusTraceEvent.State;
 
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * Lite job facade.
@@ -67,7 +69,7 @@
         executionContextService = new ExecutionContextService(regCenter, jobName);
         executionService = new ExecutionService(regCenter, jobName);
         failoverService = new FailoverService(regCenter, jobName);
-        this.elasticJobListeners = elasticJobListeners;
+        this.elasticJobListeners = elasticJobListeners.stream().sorted(Comparator.comparingInt(ElasticJobListener::order)).collect(Collectors.toList());
         this.jobTracingEventBus = null == tracingConfig ? new JobTracingEventBus() : new JobTracingEventBus(tracingConfig);
     }
     
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 016f296..e410dbe 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
@@ -25,23 +25,36 @@
 public final class TestElasticJobListener implements ElasticJobListener {
     
     private final ElasticJobListenerCaller caller;
-    
+
+    private final String name;
+
+    private final int order;
+
+    private final StringBuilder orderResult;
+
     public TestElasticJobListener() {
-        this(null);
+        this(null, null, 0, new StringBuilder());
     }
-    
+
     @Override
     public void beforeJobExecuted(final ShardingContexts shardingContexts) {
         caller.before();
+        orderResult.append(name);
     }
     
     @Override
     public void afterJobExecuted(final ShardingContexts shardingContexts) {
         caller.after();
+        orderResult.append(name);
     }
     
     @Override
     public String getType() {
         return "TEST";
     }
+
+    @Override
+    public int order() {
+        return order;
+    }
 }
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 4056e78..1a4171a 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
@@ -70,10 +70,15 @@
     private ElasticJobListenerCaller caller;
     
     private LiteJobFacade liteJobFacade;
+
+    private StringBuilder orderResult;
     
     @Before
     public void setUp() {
-        liteJobFacade = new LiteJobFacade(null, "test_job", Collections.singletonList(new TestElasticJobListener(caller)), null);
+        orderResult = new StringBuilder();
+        TestElasticJobListener l1 = new TestElasticJobListener(caller, "l1", 2, orderResult);
+        TestElasticJobListener l2 = new TestElasticJobListener(caller, "l2", 1, orderResult);
+        liteJobFacade = new LiteJobFacade(null, "test_job", Lists.newArrayList(l1, l2), null);
         ReflectionUtils.setFieldValue(liteJobFacade, "configService", configService);
         ReflectionUtils.setFieldValue(liteJobFacade, "shardingService", shardingService);
         ReflectionUtils.setFieldValue(liteJobFacade, "executionContextService", executionContextService);
@@ -198,13 +203,15 @@
     @Test
     public void assertBeforeJobExecuted() {
         liteJobFacade.beforeJobExecuted(new ShardingContexts("fake_task_id", "test_job", 10, "", Collections.emptyMap()));
-        verify(caller).before();
+        verify(caller, times(2)).before();
+        assertThat(orderResult.toString(), is("l2l1"));
     }
     
     @Test
     public void assertAfterJobExecuted() {
         liteJobFacade.afterJobExecuted(new ShardingContexts("fake_task_id", "test_job", 10, "", Collections.emptyMap()));
-        verify(caller).after();
+        verify(caller, times(2)).after();
+        assertThat(orderResult.toString(), is("l2l1"));
     }
     
     @Test