Skip to content

Commit 067785d

Browse files
committed
Implement the chain of interceptors
1 parent 6127cc6 commit 067785d

File tree

14 files changed

+411
-131
lines changed

14 files changed

+411
-131
lines changed

spring-boot-data-aggregator-autoconfigure/src/main/java/io/github/lvyahui8/spring/autoconfigure/BeanAggregateAutoConfiguration.java

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import io.github.lvyahui8.spring.aggregate.config.RuntimeSettings;
44
import io.github.lvyahui8.spring.aggregate.facade.DataBeanAggregateQueryFacade;
55
import io.github.lvyahui8.spring.aggregate.facade.impl.DataBeanAggregateQueryFacadeImpl;
6+
import io.github.lvyahui8.spring.aggregate.interceptor.AggregateQueryInterceptorChain;
7+
import io.github.lvyahui8.spring.aggregate.interceptor.impl.AggregateQueryInterceptorChainImpl;
68
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
79
import io.github.lvyahui8.spring.aggregate.repository.DataProviderRepository;
810
import io.github.lvyahui8.spring.aggregate.repository.impl.DataProviderRepositoryImpl;
@@ -15,6 +17,7 @@
1517
import org.reflections.scanners.MethodAnnotationsScanner;
1618
import org.springframework.beans.BeansException;
1719
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.beans.factory.annotation.Qualifier;
1821
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1922
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2023
import org.springframework.context.ApplicationContext;
@@ -54,22 +57,52 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
5457

5558
@Bean
5659
@ConditionalOnMissingBean
57-
public DataBeanAggregateQueryFacade dataBeanAggregateQueryFacade() {
58-
return new DataBeanAggregateQueryFacadeImpl(dataBeanAggregateQueryService());
60+
public DataBeanAggregateQueryFacade dataBeanAggregateQueryFacade(
61+
@Qualifier("dataProviderRepository") DataProviderRepository dataProviderRepository) {
62+
return new DataBeanAggregateQueryFacadeImpl(dataBeanAggregateQueryService(dataProviderRepository));
5963
}
6064

6165
@Bean
6266
@ConditionalOnMissingBean
63-
public DataBeanAggregateQueryService dataBeanAggregateQueryService () {
64-
DataProviderRepository repository = new DataProviderRepositoryImpl();
65-
scanProviders(repository);
66-
DataBeanAggregateQueryServiceImpl service = new DataBeanAggregateQueryServiceImpl(repository);
67-
service.setRuntimeSettings(createRuntimeSettings());
67+
public DataBeanAggregateQueryService dataBeanAggregateQueryService (
68+
@Qualifier("dataProviderRepository") DataProviderRepository dataProviderRepository) {
69+
if(properties.getBasePackages() != null) {
70+
for (String basePackage : properties.getBasePackages()) {
71+
Reflections reflections = new Reflections(basePackage, new MethodAnnotationsScanner());
72+
Set<Method> providerMethods = reflections.getMethodsAnnotatedWith(DataProvider.class);
73+
for (Method method : providerMethods) {
74+
DataProvider beanProvider = AnnotationUtils.findAnnotation(method, DataProvider.class);
75+
@SuppressWarnings("ConstantConditions")
76+
String dataId = beanProvider.id();
77+
Assert.isTrue(Modifier.isPublic(method.getModifiers()),"data provider method must be public");
78+
Assert.isTrue(! StringUtils.isEmpty(dataId),"data id must be not null!");
79+
DataProvideDefinition provider = DefinitionUtils.getProvideDefinition(method);
80+
provider.setId(dataId);
81+
provider.setIdempotent(beanProvider.idempotent());
82+
provider.setTimeout(beanProvider.timeout() > 0 ? beanProvider.timeout() : properties.getDefaultTimeout());
83+
dataProviderRepository.put(provider);
84+
}
85+
}
86+
}
87+
DataBeanAggregateQueryServiceImpl service = new DataBeanAggregateQueryServiceImpl();
88+
RuntimeSettings runtimeSettings = new RuntimeSettings();
89+
runtimeSettings.setEnableLogging(properties.getEnableLogging() != null
90+
? properties.getEnableLogging() : false);
91+
runtimeSettings.setIgnoreException(properties.isIgnoreException());
92+
runtimeSettings.setTimeout(properties.getDefaultTimeout());
93+
service.setRepository(dataProviderRepository);
94+
service.setRuntimeSettings(runtimeSettings);
6895
service.setExecutorService(aggregateExecutorService());
96+
service.setInterceptorChain(aggregateQueryInterceptorChain());
6997
service.setApplicationContext(applicationContext);
7098
return service;
7199
}
72100

101+
/**
102+
* 允许用户自定义线程池
103+
*
104+
* @return
105+
*/
73106
@Bean(name = "aggregateExecutorService")
74107
@ConditionalOnMissingBean(name = "aggregateExecutorService")
75108
public ExecutorService aggregateExecutorService() {
@@ -81,39 +114,21 @@ public ExecutorService aggregateExecutorService() {
81114
new CustomizableThreadFactory(properties.getThreadPrefix()));
82115
}
83116

84-
private void scanProviders(DataProviderRepository repository) {
85-
if(properties.getBasePackages() != null) {
86-
for (String basePackage : properties.getBasePackages()) {
87-
Reflections reflections = new Reflections(basePackage, new MethodAnnotationsScanner());
88-
Set<Method> providerMethods = reflections.getMethodsAnnotatedWith(DataProvider.class);
89-
for (Method method : providerMethods) {
90-
dealProviderMethod(repository, method);
91-
}
92-
}
93-
}
94-
}
95-
96-
private void dealProviderMethod(DataProviderRepository repository, Method method) {
97-
DataProvider beanProvider = AnnotationUtils.findAnnotation(method, DataProvider.class);
98-
@SuppressWarnings("ConstantConditions")
99-
String dataId = beanProvider.id();
100-
Assert.isTrue(Modifier.isPublic(method.getModifiers()),"data provider method must be public");
101-
Assert.isTrue(! StringUtils.isEmpty(dataId),"data id must be not null!");
102-
DataProvideDefinition provider = DefinitionUtils.getProvideDefinition(method);
103-
provider.setId(dataId);
104-
provider.setIdempotent(beanProvider.idempotent());
105-
provider.setTimeout(beanProvider.timeout() > 0 ? beanProvider.timeout() : properties.getDefaultTimeout());
106-
repository.put(dataId,provider);
117+
/**
118+
* 允许用户自定义provider存储
119+
*
120+
* @return
121+
*/
122+
@Bean(name = "dataProviderRepository")
123+
@ConditionalOnMissingBean(DataProviderRepository.class)
124+
public DataProviderRepository dataProviderRepository() {
125+
return new DataProviderRepositoryImpl();
107126
}
108127

109128

110-
private RuntimeSettings createRuntimeSettings() {
111-
RuntimeSettings runtimeSettings = new RuntimeSettings();
112-
runtimeSettings.setEnableLogging(properties.getEnableLogging() != null
113-
? properties.getEnableLogging() : false);
114-
runtimeSettings.setIgnoreException(properties.isIgnoreException());
115-
runtimeSettings.setTimeout(properties.getDefaultTimeout());
116-
return runtimeSettings;
129+
@Bean(name = "aggregateQueryInterceptorChain")
130+
@ConditionalOnMissingBean(AggregateQueryInterceptorChain.class)
131+
public AggregateQueryInterceptorChain aggregateQueryInterceptorChain() {
132+
return new AggregateQueryInterceptorChainImpl();
117133
}
118-
119134
}

spring-boot-data-aggregator-core/src/main/java/io/github/lvyahui8/spring/aggregate/context/AggregationContext.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.lvyahui8.spring.aggregate.context;
22

33
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
4+
import io.github.lvyahui8.spring.aggregate.model.InvokeSignature;
45
import lombok.Data;
56

67
import java.util.Map;
@@ -14,13 +15,13 @@ public class AggregationContext {
1415
/**
1516
* 发起一次递归查询的主调线程
1617
*/
17-
Thread rootThread;
18+
Thread rootThread;
1819
/**
1920
* 根provider
2021
*/
21-
DataProvideDefinition rootProvideDefinition;
22+
DataProvideDefinition rootProvideDefinition;
2223
/**
2324
* 此次查询生命周期中的缓存
2425
*/
25-
Map<String,Object> cacheMap;
26+
Map<InvokeSignature,Object> cacheMap;
2627
}

spring-boot-data-aggregator-core/src/main/java/io/github/lvyahui8/spring/aggregate/facade/impl/DataBeanAggregateQueryFacadeImpl.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.github.lvyahui8.spring.aggregate.facade.impl;
22

3-
import io.github.lvyahui8.spring.aggregate.consts.AggregationConstant;
43
import io.github.lvyahui8.spring.aggregate.facade.DataBeanAggregateQueryFacade;
54
import io.github.lvyahui8.spring.aggregate.func.MultipleArgumentsFunction;
65
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
@@ -13,7 +12,6 @@
1312
import java.lang.reflect.Modifier;
1413
import java.util.Collections;
1514
import java.util.Map;
16-
import java.util.concurrent.ConcurrentHashMap;
1715

1816

1917
/**
@@ -35,8 +33,7 @@ public <T> T get(String id, Map<String,Object> invokeParams, Class<T> clazz) thr
3533
if(invokeParams == null) {
3634
invokeParams = Collections.emptyMap();
3735
}
38-
return dataBeanAggregateQueryService.get(id,invokeParams,clazz,
39-
new ConcurrentHashMap<>(AggregationConstant.DEFAULT_INITIAL_CAPACITY));
36+
return dataBeanAggregateQueryService.get(id,invokeParams,clazz);
4037
}
4138

4239
@Override
@@ -74,8 +71,7 @@ public <T> T get(Map<String, Object> invokeParams, MultipleArgumentsFunction<T>
7471
}
7572
try {
7673
@SuppressWarnings("unchecked")
77-
T ret = (T) dataBeanAggregateQueryService.get(provider, invokeParams, applyMethod.getReturnType(),
78-
new ConcurrentHashMap<>(AggregationConstant.DEFAULT_INITIAL_CAPACITY));
74+
T ret = (T) dataBeanAggregateQueryService.get(provider, invokeParams, applyMethod.getReturnType());
7975

8076
return ret;
8177
} finally {
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* @author lvyahui (lvyahui8@gmail.com,lvyahui8@126.com)
1010
* @since 2019/7/21 22:28
1111
*/
12-
public interface AbstractAggregateQueryInterceptor {
12+
public interface AggregateQueryInterceptor {
1313
/**
1414
* 查询正常提交, Context已经创建
1515
*
@@ -23,9 +23,8 @@ public interface AbstractAggregateQueryInterceptor {
2323
*
2424
* @param aggregationContext 查询上下文
2525
* @param provideDefinition 将被执行的Provider
26-
* @return 返回为true才继续执行
2726
*/
28-
boolean queryBefore(AggregationContext aggregationContext, DataProvideDefinition provideDefinition);
27+
void queryBefore(AggregationContext aggregationContext, DataProvideDefinition provideDefinition);
2928

3029
/**
3130
* 每个Provider方法执行成功之后, 调用此方法. 存在并发调用
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package io.github.lvyahui8.spring.aggregate.interceptor;
2+
3+
import io.github.lvyahui8.spring.aggregate.context.AggregationContext;
4+
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
5+
6+
/**
7+
* @author lvyahui (lvyahui8@gmail.com,lvyahui8@126.com)
8+
* @since 2019/8/4 15:10
9+
*/
10+
public interface AggregateQueryInterceptorChain {
11+
/**
12+
* 新增一个拦截器
13+
*
14+
* @param queryInterceptor 新增的拦截器
15+
*/
16+
void addInterceptor(AggregateQueryInterceptor queryInterceptor) ;
17+
18+
/**
19+
* 顺序调用拦截器前置处理, 查询正常提交, Context已经创建
20+
*
21+
* @param aggregationContext 查询上下文
22+
* @return 是否提前结束
23+
*/
24+
boolean applyQuerySubmitted(AggregationContext aggregationContext);
25+
/**
26+
* 顺序调用拦截器前置处理, 每个Provider方法执行前, 将调用此方法. 存在并发调用
27+
*
28+
* @param aggregationContext 查询上下文
29+
* @param provideDefinition 将被执行的Provider
30+
*/
31+
void applyQueryBefore(AggregationContext aggregationContext, DataProvideDefinition provideDefinition);
32+
33+
/**
34+
* 顺序调用拦截器前置处理, 每个Provider方法执行成功之后, 调用此方法. 存在并发调用
35+
* @param aggregationContext 查询上下文
36+
* @param provideDefinition 被执行的Provider
37+
* @param result 查询结果
38+
* @return 链式处理后的结果
39+
*/
40+
Object applyQueryAfter(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Object result);
41+
42+
/**
43+
* 顺序调用拦截器前置处理, 每个Provider执行时, 如果抛出异常, 将调用此方法. 存在并发调用
44+
*
45+
* @param aggregationContext 查询上下文
46+
* @param provideDefinition 被执行的Provider
47+
* @param e Provider抛出的异常
48+
*/
49+
void applyExceptionHandle(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Exception e);
50+
51+
/**
52+
* 顺序调用拦截器前置处理, 一次查询全部完成.
53+
*
54+
* @param aggregationContext 查询上下文
55+
*/
56+
void applyQueryFinished(AggregationContext aggregationContext);
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.github.lvyahui8.spring.aggregate.interceptor.impl;
2+
3+
import io.github.lvyahui8.spring.aggregate.context.AggregationContext;
4+
import io.github.lvyahui8.spring.aggregate.interceptor.AggregateQueryInterceptor;
5+
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
6+
7+
/**
8+
* @author lvyahui (lvyahui8@gmail.com,lvyahui8@126.com)
9+
* @since 2019/8/4 15:16
10+
*/
11+
public class AggregateQueryInterceptorAdapter implements AggregateQueryInterceptor {
12+
@Override
13+
public boolean querySubmitted(AggregationContext aggregationContext) {
14+
return true;
15+
}
16+
17+
@Override
18+
public void queryBefore(AggregationContext aggregationContext, DataProvideDefinition provideDefinition) {
19+
20+
}
21+
22+
@Override
23+
public Object queryAfter(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Object result) {
24+
return result;
25+
}
26+
27+
@Override
28+
public void exceptionHandle(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Exception e) {
29+
30+
}
31+
32+
@Override
33+
public void queryFinished(AggregationContext aggregationContext) {
34+
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package io.github.lvyahui8.spring.aggregate.interceptor.impl;
2+
3+
import io.github.lvyahui8.spring.aggregate.context.AggregationContext;
4+
import io.github.lvyahui8.spring.aggregate.interceptor.AggregateQueryInterceptor;
5+
import io.github.lvyahui8.spring.aggregate.interceptor.AggregateQueryInterceptorChain;
6+
import io.github.lvyahui8.spring.aggregate.model.DataProvideDefinition;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
/**
12+
* @author lvyahui (lvyahui8@gmail.com,lvyahui8@126.com)
13+
* @since 2019/8/4 15:22
14+
*/
15+
public class AggregateQueryInterceptorChainImpl implements AggregateQueryInterceptorChain {
16+
17+
private List<AggregateQueryInterceptor> interceptors;
18+
19+
private List<AggregateQueryInterceptor> initInterceptors() {
20+
if(this.interceptors == null) {
21+
synchronized (this) {
22+
if(this.interceptors == null) {
23+
this.interceptors = new ArrayList<>(1);
24+
}
25+
}
26+
}
27+
return this.interceptors;
28+
}
29+
30+
@Override
31+
public void addInterceptor(AggregateQueryInterceptor queryInterceptor) {
32+
this.initInterceptors().add(queryInterceptor);
33+
}
34+
35+
@Override
36+
public boolean applyQuerySubmitted(AggregationContext aggregationContext) {
37+
for (AggregateQueryInterceptor interceptor : this.initInterceptors()) {
38+
if(!interceptor.querySubmitted(aggregationContext)) {
39+
return false;
40+
}
41+
}
42+
return true;
43+
}
44+
45+
@Override
46+
public void applyQueryBefore(AggregationContext aggregationContext, DataProvideDefinition provideDefinition) {
47+
for (AggregateQueryInterceptor interceptor : this.initInterceptors()) {
48+
interceptor.queryBefore(aggregationContext,provideDefinition);
49+
}
50+
}
51+
52+
@Override
53+
public Object applyQueryAfter(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Object result) {
54+
for (AggregateQueryInterceptor interceptor : this.initInterceptors()) {
55+
result = interceptor.queryAfter(aggregationContext,provideDefinition,result);
56+
}
57+
return result;
58+
}
59+
60+
@Override
61+
public void applyExceptionHandle(AggregationContext aggregationContext, DataProvideDefinition provideDefinition, Exception e) {
62+
for (AggregateQueryInterceptor interceptor : this.initInterceptors()) {
63+
interceptor.exceptionHandle(aggregationContext,provideDefinition,e);
64+
}
65+
}
66+
67+
@Override
68+
public void applyQueryFinished(AggregationContext aggregationContext) {
69+
for (AggregateQueryInterceptor interceptor : this.initInterceptors()) {
70+
interceptor.queryFinished(aggregationContext);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)