Bootstrap

Java 接口多实现动态调用

简单定义一个接口,做数据插入

public interface ImportingData<T> {
    AjaxResult addData(T t);
}

目前本文使用的是根据泛型类实现动态调用,在引入时必须明确是那个实体类,
还有种方法就是给每一个实现类定义业务类型的枚举,这时候子啊接口里面就得多写一个返回枚举的实现

 implements ImportingData<XXXX>

这里获取每一个实现以及对应的泛型类组成map,这样就能根据map特性动态调用

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.GenericTypeResolver;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;


@Component
public class ApplicationContextFactory implements ApplicationContextAware {

    private final Map<Class<?>, ImportingData<Object>> importingDataService = new HashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        applicationContext.getBeansOfType(ImportingData.class)
                .forEach((k, v) -> importingDataService.put(GenericTypeResolver.resolveTypeArgument(v.getClass(), ImportingData.class), v));
    }

    public <T> ImportingData<Object> getImportingDataService(Class<T> c) {
        return importingDataService.get(c);

    }


}

来个例子

定义一个实体类,实体类里面包含了两个泛型实现 implements ImportingData

@Data
public class Importing {

    @Valid
    private AAA aaa;
    @Valid
    private BBB bbb;
    
}
 public void addAll(Importing importing) {
 		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //拿到数据成员
        List<Method> methodList = Arrays.asList(importing.getClass().getDeclaredMethods());
        methodList.parallelStream().forEach(n -> {
        //根据反射拿到实体类的get对象
            if (n.getName().startsWith("get")) {
                Object invoke = null;
                try {
                    invoke = n.invoke(importing);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
                if (ObjectUtil.isNotNull(invoke)) {
                //调用
                    addDataAndLogAsync(n.getReturnType(), invoke, authentication);
                }
            }
        });
       
    }
    private Future<AjaxResult> addDataAndLogAsync(Class<?> returnType, Object invoke, Authentication authentication) {
    //因为是异步请求,可能涉及到用户获取之类的所以手动传播上下文,没有的可以不用
        return executorService.submit(() -> {
            SecurityContextHolder.getContext().setAuthentication(authentication);
            AjaxResult ajaxResult = null;
            //这里可以定义日志啥的
            try {
            //这里getImportingDataService可能为空,可以加一层判断
                ajaxResult = applicationContextFactory.getImportingDataService(returnType).addData(invoke);            
            } catch (Exception e) {
                log.error("数据异常:", e);
            }
            return ajaxResult;
        });
    }
    ```

这样的话实体类不管加多少只要是实现了都可以动态调用
;