- config添加切面增强器的bean
package com.hj.config;
import com.hj.mergeprocess.MergeProcessBefore;
import com.hj.mergeprocess.annotation.MergeProcessMethodAnnotation;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author huangjie
*/
@Configuration
public class MergeProcessAopBeanConfig {
@Bean
public MergeProcessBefore mergeProcessBefore(){
return new MergeProcessBefore();
}
@Bean
public AnnotationMatchingPointcut annotationMatchingPointcut(){
return AnnotationMatchingPointcut.forMethodAnnotation(MergeProcessMethodAnnotation.class);
}
@Bean
public Advisor registerAdvisor(){
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(annotationMatchingPointcut());
defaultPointcutAdvisor.setAdvice(mergeProcessBefore());
defaultPointcutAdvisor.setOrder(10);
return defaultPointcutAdvisor;
}
}
- 自定义注解
package com.hj.mergeprocess.annotation;
import com.hj.mergeprocess.AbstractMergeProcessHandler;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MergeProcessMethodAnnotation {
int concurrencyCount() default 10;
Class<? extends AbstractMergeProcessHandler> mergeProcessHandler();
}
- 相关接口和处理类
package com.hj.mergeprocess; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.LinkedBlockingDeque; import java.util.function.Function; public abstract class AbstractMergeProcessHandler<T> implements MergeProcessHandler<T>{ LinkedBlockingDeque<RequestEntity<T>> deque = new LinkedBlockingDeque<>(); private void addRequestEntity(RequestEntity<T> requestEntity) { deque.addLast(requestEntity); } protected void processRequest(Function<List<RequestEntity<T>>, Map<String ,T>> function, int concurrencyCount) { int size = deque.size(); List<RequestEntity<T>> requestEntities = new ArrayList<>(size); List<RequestEntity<T>> futureEntityList = new ArrayList<>(size); for (int i = deque.size(); i > 0; i--) { RequestEntity<T> requestEntity = deque.poll(); requestEntities.add(requestEntity); futureEntityList.add(requestEntity); } if(size>concurrencyCount){ Map<String, T> result = doProcessRequest(requestEntities, function); for (RequestEntity<T> requestEntity : futureEntityList) { String requestId = requestEntity.getRequestId(); T responseEntity = result.get(requestId); requestEntity.getFuture().complete(responseEntity); } return; } for (RequestEntity<T> requestEntity : futureEntityList) { requestEntity.getFuture().complete(null); } } protected void addRequestPerThread(ThreadLocal<CompletableFuture<T>> threadLocal,Object requestBody,String requestId){ CompletableFuture<T> future = new CompletableFuture<>(); threadLocal.set(future); RequestEntity<T> requestEntity = new RequestEntity<>(); requestEntity.setRequestBody(requestBody); requestEntity.setRequestId(requestId); requestEntity.setFuture(future); addRequestEntity(requestEntity); } protected int getQueueSize(){ return deque.size(); } private Map<String, T> doProcessRequest(List<RequestEntity<T>> requestEntities, Function<List<RequestEntity<T>>, Map<String, T>> function) { return function.apply(requestEntities); } protected abstract Object packageQueryArgs(Object[] args); protected abstract String getRequestId(Object arg); }
package com.hj.mergeprocess;
import com.hj.mergeprocess.annotation.MergeProcessMethodAnnotation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
public class MergeProcessBefore implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
MergeProcessInterface mergeProcessInterface = (MergeProcessInterface) invocation.getThis();
Class<?> clazz = Class.forName(invocation.getThis().getClass().getName());
Method method = clazz.getMethod(invocation.getMethod().getName(), invocation.getMethod().getParameterTypes());
MergeProcessMethodAnnotation annotation = method.getAnnotation(MergeProcessMethodAnnotation.class);
String simpleBeanName = annotation.mergeProcessHandler().getSimpleName();
//获取对应的bean service
MergeProcessHandler mergeProcessHandler = CustomerContext.getApplicationContext().getBean(toLowerCaseFirstOne(simpleBeanName), MergeProcessHandler.class);
ThreadLocal<CompletableFuture<Object>> futureThreadLocal = mergeProcessInterface.getFutureThreadLocal();
mergeProcessHandler.mergeProcess(futureThreadLocal, invocation.getArguments(), annotation.concurrencyCount());
return invocation.proceed();
}
private String toLowerCaseFirstOne(String simpleBeanName) {
Character.isLowerCase(simpleBeanName.charAt(0)) {
return simpleBeanName;
}
return Character.toLowerCase(simpleBeanName.charAt(0)) + simpleBeanName.substring(1);
}
}
package com.hj.mergeprocess;
import java.util.concurrent.CompletableFuture;
public interface MergeProcessHandler<T> {
void mergeProcess(ThreadLocal<CompletableFuture<T>> threadLocal, Object[] args, int concurrencyCount);
}
package com.hj.mergeprocess;
import java.util.concurrent.CompletableFuture;
public interface MergeProcessInterface {
ThreadLocal<CompletableFuture<Object>> getFutureThreadLocal();
}
package com.hj.mergeprocess;
import lombok.Data;
import java.io.Serializable;
import java.util.concurrent.CompletableFuture;
public class RequestEntity<T> implements Serializable {
/**
* 请求唯一标志id
*/
String requestId;
/**
* 请求体参数
*/
Object requestBody;
/**
* 请求回调future
*/
CompletableFuture<T> future;
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public Object getRequestBody() {
return requestBody;
}
public void setRequestBody(Object requestBody) {
this.requestBody = requestBody;
}
public CompletableFuture<T> getFuture() {
return future;
}
public void setFuture(CompletableFuture<T> future) {
this.future = future;
}
}
package com.hj.mergeprocess;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/**
* @author huangjie
*/
@Component
public class ViewMergeProcess extends AbstractMergeProcessHandler<Object> {
@Override
public void mergeProcess(ThreadLocal<CompletableFuture<Object>> threadLocal, Object[] args, int concurrencyCount) {
//封装请求参数
packageQueryArgs(args);
String requestId = getRequestId("");
//添加请求
addRequestPerThread(threadLocal,null, requestId);
//...定时获取deque里面的数据判断是否做处理
//...
if (lock.tryLock()) {
try {
TimeUnit.MICROSECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
if (getQueueSize()==0) {
return;
}
//processRequest(...)
}
//处理 自己传入future()
processRequest(new Function<List<RequestEntity<Object>>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(List<RequestEntity<Object>> requestEntities) {
return null;
}
},concurrencyCount);
//处理 自己传入future()
processRequest(new Function<List<RequestEntity<Object>>, Map<String, Object>>() {
@Override
public Map<String, Object> apply(List<RequestEntity<Object>> requestEntities) {
return null;
}
},concurrencyCount);
}
@Override
protected Object packageQueryArgs(Object[] args) {
return null;
}
public String getRequestId(Object obj){
return UUID.randomUUID().toString();
}
}