新增集装箱,根据进出口类型,分别进行不同的操作. (这里我只比较进出口两个类型,实际代码中根据业务类型的不同可能存在多次判断, 会出现大批的if /else if/ else…)
package com.howhan.cloud.e.common.enums;
public enum ImportExportTypeEnum {
IMPORT(0, "进口"),
EXPORT(1, "出口");
private final Integer value;
private final String desc;
private final String name;
private ImportExportTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
this.name = this.name();
}
public Integer getValue() {
return this.value;
}
public String getDesc() {
return this.desc;
}
public String getName() {
return this.name;
}
}
public void newContainer(Long orderId,CustomerContainerVO vo){
CustomerOrder order = customerOrderService.getById(orderId);
if(ImportExportTypeEnum.EXPORT == order.getImportExportType()){//出口
//do something
}else{//进口
//do something
}
//这里我只比较进出口两个类型,实际代码中根据业务类型的不同可能存在多次判断
//会出现大批的if /else if/ else...
}
@Override
public SimpleTuber<Void> newContainer(Long orderId,CustomerContainerVO vo) {
CustomerOrder order = customerOrderService.getById(orderId);
Handler handler = SpringBeanUtil.getBean(
NewContainerHandle.class,
order.getImportExportType()
);
return handler.handle(orderId,vo);
}
package com.howhan.cloud.e.order.service.annotation;
import com.howhan.cloud.e.common.enums.ImportExportTypeEnum;
import java.lang.annotation.*;
/**
* 新增箱
* 进出口 处理句柄 handler标记注解
* @author Kaizen
* */
@Inherited //子类继承注解,如 CGLIB 生成带代理类 可以继承此注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NewContainerHandle {
ImportExportTypeEnum value();
}
package com.howhan.cloud.e.order.service.handler;
import wiki.kaizen.cloud.plugin.spring.SimpleTuber;
/**
*处理器超类
* */
public interface Handler {
SimpleTuber<Void> handle(Object... args);
}
package com.howhan.cloud.e.order.service.handler.container;
import com.howhan.cloud.e.order.service.handler.Handler;
import com.howhan.cloud.e.order.service.o.vo.CustomerContainerVO;
import lombok.extern.slf4j.Slf4j;
import wiki.kaizen.cloud.plugin.spring.SimpleTuber;
/**
* 新增箱抽象处理类
* 对超类参数进一步处理
* @author Kaizen
* */
@Slf4j
public abstract class AbstractNewContainerHandler implements Handler {
/**
* @param args 长度为2 第一个为Long orderId,第二个传参的vo CustomerContainerVO
* */
@Override
public SimpleTuber<Void> handle(Object... args){
if (args == null ||args.length !=2){
log.error("Handler#handle(args...) 参数设置不正确 应为 handle(Long orderId,CustomerContainerVO vo)");
return SimpleTuber.error("服务器发生异常");
}
Long orderId ;
CustomerContainerVO vo;
try{
orderId =(Long) args[0];
vo =(CustomerContainerVO)args[1];
}catch (Exception ignore){
log.error("Handler#handle(args...) 参数设置不正确 应为 handle(Long orderId,CustomerContainerVO vo)");
return SimpleTuber.error("服务器发生异常");
}
return build(orderId,vo);
}
/**
* 真实业务逻辑
* */
public abstract SimpleTuber<Void> build(Long orderId, CustomerContainerVO vo);
}
package com.howhan.cloud.e.order.service.handler.container;
import com.howhan.cloud.e.common.enums.ImportExportTypeEnum;
import com.howhan.cloud.e.order.service.annotation.NewContainerHandle;
import com.howhan.cloud.e.order.service.o.vo.CustomerContainerVO;
import org.springframework.stereotype.Service;
import wiki.kaizen.cloud.plugin.spring.SimpleTuber;
import java.time.LocalDateTime;
/**
* 新增 进口箱 处理
* @author Kaizen
* */
@Service
@NewContainerHandle(ImportExportTypeEnum.IMPORT)
public class NewImportContainerHadnler extends AbstractNewContainerHandler {
@Override
public SimpleTuber<Void> build(Long orderId, CustomerContainerVO vo){
//专注进口业务处理 do something
return SimpleTuber.OK();
}
}
package com.howhan.cloud.e.order.service.handler.container;
import com.howhan.cloud.e.common.enums.ImportExportTypeEnum;
import com.howhan.cloud.e.order.service.annotation.NewContainerHandle;
import com.howhan.cloud.e.order.service.o.vo.CustomerContainerVO;
import org.springframework.stereotype.Service;
import wiki.kaizen.cloud.plugin.spring.SimpleTuber;
/**
* 新增 出口箱 处理
* @author Kaizen
* */
@Service
@NewContainerHandle(ImportExportTypeEnum.EXPORT)
public class NewExportContainerHandler extends AbstractNewContainerHandler {
@Override
public SimpleTuber<Void> build(Long orderId, CustomerContainerVO vo){
//专注进口业务处理 do something
return SimpleTuber.OK();
}
}
package wiki.kaizen.cloud.plugin.spring.scan.compent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@Component
@Slf4j
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
if (SpringBeanUtil.applicationContext == null) {
SpringBeanUtil.applicationContext = applicationContext;
}
}
public static <A extends Annotation> Map<String, Object> getBeansWithAnnotation(Class<A> annoClass){
return applicationContext.getBeansWithAnnotation(annoClass);
}
/**
* 根据注解及注解的值获取 对应的Bean
* 要求 注解必须包含方法value 且为空参
* */
@SuppressWarnings("unchecked")
public static < B,A extends Annotation, E> B getBean(Class<A> annoClass, E em){
Objects.requireNonNull(annoClass,"注解的值不能为空");
Objects.requireNonNull(em,"注解value对应的值不能为空");
Map<String, Object> beans = getBeansWithAnnotation(annoClass);
Method value;
try {
value = annoClass.getDeclaredMethod("value");
} catch (NoSuchMethodException e) {
log.error(annoClass.getSimpleName()+"注解,未设置value方法");
return null;
}
value.setAccessible(true);
Optional<B> any = beans.values().stream().filter(
bean -> {
A anno = Optional.ofNullable(
bean.getClass().getAnnotation(annoClass)
).orElse(
bean.getClass().getSuperclass().getAnnotation(annoClass)
);
if (anno == null){
log.error("未正确获取注解,请给注解设置@Inherited");
return false;
}
E e;
try {
e = (E) value.invoke(anno);
} catch (IllegalAccessException | InvocationTargetException ex) {
return false;
}
return em == e || em.equals(e);
}
).map(bean -> (B) bean).findAny();
return any.orElseGet(
()->{
log.error("未能从Spring容器中获取到{}对应的Bean",em.getClass());
return null;
}
);
}
}