6
6
import io .github .lvyahui8 .spring .aggregate .interceptor .AggregateQueryInterceptor ;
7
7
import io .github .lvyahui8 .spring .aggregate .interceptor .AggregateQueryInterceptorChain ;
8
8
import io .github .lvyahui8 .spring .aggregate .interceptor .impl .AggregateQueryInterceptorChainImpl ;
9
+ import io .github .lvyahui8 .spring .aggregate .model .DataConsumeDefinition ;
9
10
import io .github .lvyahui8 .spring .aggregate .model .DataProvideDefinition ;
10
11
import io .github .lvyahui8 .spring .aggregate .repository .DataProviderRepository ;
11
12
import io .github .lvyahui8 .spring .aggregate .repository .impl .DataProviderRepositoryImpl ;
14
15
import io .github .lvyahui8 .spring .aggregate .util .DefinitionUtils ;
15
16
import io .github .lvyahui8 .spring .annotation .DataProvider ;
16
17
import lombok .extern .slf4j .Slf4j ;
18
+ import org .apache .commons .lang3 .StringUtils ;
17
19
import org .reflections .Reflections ;
18
20
import org .reflections .scanners .MethodAnnotationsScanner ;
19
21
import org .springframework .beans .BeansException ;
30
32
import org .springframework .core .annotation .Order ;
31
33
import org .springframework .scheduling .concurrent .CustomizableThreadFactory ;
32
34
import org .springframework .util .Assert ;
33
- import org .springframework .util .StringUtils ;
34
35
35
36
import java .lang .reflect .Method ;
36
37
import java .lang .reflect .Modifier ;
39
40
import java .util .concurrent .LinkedBlockingDeque ;
40
41
import java .util .concurrent .ThreadPoolExecutor ;
41
42
import java .util .concurrent .TimeUnit ;
43
+ import java .util .stream .Collectors ;
42
44
43
45
/**
44
46
@@ -65,11 +67,44 @@ public DataBeanAggregateQueryFacade dataBeanAggregateQueryFacade(
65
67
return new DataBeanAggregateQueryFacadeImpl (dataBeanAggregateQueryService (dataProviderRepository ));
66
68
}
67
69
70
+ private void checkCycle (Map <String ,Set <String >> graphAdjMap ) {
71
+ Map <String ,Integer > visitStatusMap = new HashMap <>(graphAdjMap .size () * 2 );
72
+ Stack <String > stack = new Stack <>();
73
+ for (Map .Entry <String , Set <String >> item : graphAdjMap .entrySet ()) {
74
+ if (visitStatusMap .containsKey (item .getKey ())) {
75
+ continue ;
76
+ }
77
+ dfs (graphAdjMap ,visitStatusMap ,item .getKey ());
78
+ }
79
+ }
80
+
81
+ private void dfs (Map <String ,Set <String >> graphAdjMap ,Map <String ,Integer > visitStatusMap , String node ) {
82
+ if (visitStatusMap .containsKey (node )) {
83
+ if (visitStatusMap .get (node ) == 1 ) {
84
+ List <String > relatedNodes = new ArrayList <>();
85
+ for (Map .Entry <String ,Integer > item : visitStatusMap .entrySet ()) {
86
+ if (item .getValue () == 1 ) {
87
+ relatedNodes .add (item .getKey ());
88
+ }
89
+ }
90
+ throw new IllegalStateException ("There are loops in the dependency graph. Related nodes:" + StringUtils .join (relatedNodes ));
91
+ }
92
+ return ;
93
+ }
94
+ visitStatusMap .put (node ,1 );
95
+ log .info ("visited:{}" , node );
96
+ for (String relateNode : graphAdjMap .get (node )) {
97
+ dfs (graphAdjMap ,visitStatusMap ,relateNode );
98
+ }
99
+ visitStatusMap .put (node ,2 );
100
+ }
101
+
68
102
@ Bean
69
103
@ ConditionalOnMissingBean
70
104
public DataBeanAggregateQueryService dataBeanAggregateQueryService (
71
105
@ Qualifier ("dataProviderRepository" ) DataProviderRepository dataProviderRepository ) {
72
106
if (properties .getBasePackages () != null ) {
107
+ Map <String ,Set <String >> provideDependMap = new HashMap <>();
73
108
for (String basePackage : properties .getBasePackages ()) {
74
109
Reflections reflections = new Reflections (basePackage , new MethodAnnotationsScanner ());
75
110
Set <Method > providerMethods = reflections .getMethodsAnnotatedWith (DataProvider .class );
@@ -80,13 +115,18 @@ public DataBeanAggregateQueryService dataBeanAggregateQueryService (
80
115
Assert .isTrue (Modifier .isPublic (method .getModifiers ()),"data provider method must be public" );
81
116
Assert .isTrue (! StringUtils .isEmpty (dataId ),"data id must be not null!" );
82
117
DataProvideDefinition provider = DefinitionUtils .getProvideDefinition (method );
118
+
83
119
provider .setId (dataId );
84
120
provider .setIdempotent (beanProvider .idempotent ());
85
121
provider .setTimeout (beanProvider .timeout () > 0 ? beanProvider .timeout () : properties .getDefaultTimeout ());
122
+ Assert .isTrue (! dataProviderRepository .contains (dataId ), "Data providers with the same name are not allowed. dataId: " + dataId );
123
+ provideDependMap .put (dataId ,provider .getDepends ().stream ().map (DataConsumeDefinition ::getId ).collect (Collectors .toSet ()));
86
124
dataProviderRepository .put (provider );
87
125
}
88
126
}
127
+ checkCycle (provideDependMap );
89
128
}
129
+
90
130
DataBeanAggregateQueryServiceImpl service = new DataBeanAggregateQueryServiceImpl ();
91
131
RuntimeSettings runtimeSettings = new RuntimeSettings ();
92
132
runtimeSettings .setEnableLogging (properties .getEnableLogging () != null
0 commit comments