需求:
去掉侵入性代码,方法如参加上动态选举的注解又springboot-AOP切入方法,在方法执行前选举实现FileUploadService接口的指定子类作为参数传入处理不同业务
代码:
package com.kili.file.config.elect;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
/**
* List of parameters to be checked
*
* @author .....
* @since 2019/07/25
*/
@Getter
@Setter
@Slf4j
@Configuration
@PropertySource("classpath:valid.properties")
@ConfigurationProperties(prefix = "valid")
@ConditionalOnProperty(value = "custom.valid.enable", havingValue = "true")
public class ValidConfiguration {
@Resource
private Environment environment;
private List<String> keys;
/**
* Check whether the specified key exists and there is no system termination
*/
@PostConstruct
public void valid() {
Optional.ofNullable(keys).
orElseThrow(() -> new NullPointerException("System config loaded for error Not exists key ,please check to your properties")).
stream().
map(var -> {
String var1 = environment.getProperty(var);
if (environment.getProperty(var1) == null || this.internalElementValid(var1)) {log.error("Service value corresponding to value is not valid");System.exit(-1);}//The other valid
return var;
});
}
public boolean internalElementValid(String ln) {
boolean flag = false;
int ci = ln.indexOf('#');
if (ci >= 0) {
ln = ln.substring(0, ci);
}
ln = ln.trim();
int n = ln.length();
if (n != 0) {
if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
log.error("Illegal configuration-file syntax");
flag = true;
}
int cp = ln.codePointAt(0);
if (!Character.isJavaIdentifierStart(cp)) {
log.error("Illegal provider-service path: " + ln);
flag = true;
}
for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
cp = ln.codePointAt(i);
if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
log.error("Illegal provider-service path: " + ln);
flag = true;
}
}
return flag;
}
}
}
import com.kili.file.config.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
/**
* @author xxxx
* @since 2019/07/24
*/
@Slf4j
public class DynamicElectResolver implements HandlerMethodArgumentResolver {
@Resource
private DynamicElectConfiguration dynamicElectConfiguration;
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(DynamicElect.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
Object result;
//Getting annotation information
DynamicElect dynamicElect = methodParameter.getParameterAnnotation(DynamicElect.class);
String beanName = null;
switch (dynamicElect.mode()) {
case PARAMETER:
beanName = nativeWebRequest.getParameter(dynamicElect.key());
break;
default:
break;
}
log.info("key in parameter = {}", beanName);
//Get the corresponding dynamic election group,Get the corresponding beanName from the mapping configuration
LinkedHashMap<String, String> values = dynamicElectConfiguration.getMapper().get(dynamicElect.group());
//Failure to find the corresponding mapping makes the first default
if (!StringUtils.hasText(beanName = values.get(beanName))) {
beanName = values.get(values.keySet().iterator().next());
}
log.info("Setting the implementation class name dynamically = {}", beanName);
//Find the corresponding implementation class in the container and return it
result = SpringContextHolder.getBean(beanName);
return result;
}
很明显主要处理逻辑又实现HandlerMethodArgumentResolver类实现。
注解实现如下
/**
* @author
* @since 2019/07/24
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DynamicElect {
/**
* group
*/
String group() default "default";
/**
* Parameter key
*/
String key() default "target";
/**
* get parameter mode
*/
DynamicElectMode mode() default DynamicElectMode.PARAMETER;
/**
* parameter source mode ,different mode for elect such as x-form-url-encode
*
* @author
* @since 2019/07/24
*/
enum DynamicElectMode {
/**
* request.getParameter(value)
*/
PARAMETER
}
}
valid.properties
valid.keys[0]=dynamic.elect.mapper.default.OSS valid.keys[1]=dynamic.elect.mapper.default.S3
这里说明一下代码中的WebAsyncTask这个类是spring5.0提供的一个异步事件回调类,用于异步逻辑处理,相比较还有一个@Async的注解但是这个注解只能起到多线程截藕的情况,如果操作耗时较长主线程任然会阻塞,感兴趣的可以去查一下这里提一下。