平台listener改造方案

技术spring容器注入,springboot启动,javassist动态给类产生注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ImportEventServiceDefineIdRegistrar.class)
/**
 * EventService使用的启用类
 */
public @interface EnableEventService {

    /**
     * 扫描路径
     * @return
     */
    String[] basePackages() default { "com.thoughtworks" };

    /**
     * 支持的方式,现支持3种:id,code,all
     * @return
     */
    BillEventSupportType supportType() default BillEventSupportType.ALL;

}

/**
 * EventServiceDefineId的注入,同时把DefineCode放入DefineCodeBeanDefinitionRegistrarContext中,在spring启动前,再处理DefineCodeBeanDefinitionRegistrarContext
 */
public class ImportEventServiceDefineIdRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        //注入billEventListener,billEventListener为什么不是用@Compoent注解?为了在不启用的情况下,不影响原来逻辑
        CoreBeanDefinitionRegistrarContext.register(beanDefinitionRegistry);
        //设置DefineCodeBeanDefinitionRegistrarContext的beandefinition的注册器
        DefineCodeBeanDefinitionRegistrarContext.setBeanDefinitionRegistry(beanDefinitionRegistry);
        //获取注解的扫描器
        EventServiceClassPathScanningCandidateComponentProvider classPathScanningCandidateComponentProvider = new EventServiceClassPathScanningCandidateComponentProvider();
        //获取EnableEventService注解上配置的属性
        Map<String, Object> attrs = annotationMetadata.getAnnotationAttributes(EnableEventService.class.getName());
        //获取需要扫描的路径
        ScanParam scanParam = new ScanParam((String[])attrs.get("basePackages"), (BillEventSupportType)attrs.get("supportType"));
        //遍历扫描路径
        for (String basePackage : scanParam.getBasePackages()) {
            //扫描得到的BeanDefinition的集合
            Set<BeanDefinition> eventServiceSet = classPathScanningCandidateComponentProvider.findCandidateComponents(basePackage);
            //遍历集合注入到spring容器中
            for (BeanDefinition eventServiceBeanDefinition : eventServiceSet) {
                //生成beanid
                Set<String> beanIds = EventServiceBeanIdGenerator.getBeanIds(eventServiceBeanDefinition, scanParam);
                for (String beanId : beanIds) {
                    if (beanId != null) {
                        if (beanDefinitionRegistry.containsBeanDefinition(beanId)) {
                            throw new EventServiceException(beanId + "在spring容器中已经存在");
                        }
                        //放入spring容器
                        beanDefinitionRegistry.registerBeanDefinition(beanId, eventServiceBeanDefinition);
                    }
                }
            }
        }

    }

    /**
     * EventService注解扫描器
     */
    class EventServiceClassPathScanningCandidateComponentProvider extends ClassPathScanningCandidateComponentProvider {
        @Override
        protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
            //只扫描3类注解
            return metadataReader.getAnnotationMetadata().hasAnnotation(BillEventService.class.getName()) ||
                    metadataReader.getAnnotationMetadata().hasAnnotation(BoEventService.class.getName()) ||
                    metadataReader.getAnnotationMetadata().hasAnnotation(WfEventService.class.getName());
        }
    }

    /**
     * 扫描参数
     */
    class ScanParam {

        private String[] basePackages;

        private BillEventSupportType billEventSupportType;

        public ScanParam(String[] basePackages, BillEventSupportType billEventSupportType) {
            this.basePackages = basePackages;
            this.billEventSupportType = billEventSupportType;
        }

        public String[] getBasePackages() {
            return basePackages;
        }

        public BillEventSupportType getBillEventSupportType() {
            return billEventSupportType;
        }

    }
    /**
     * eventService beanId生成器,策略模式分发到3类生成器去处理
     */
    static class EventServiceBeanIdGenerator {

        public static Set<String> getBeanIds(BeanDefinition eventServiceBeanDefinition, ScanParam scanParam) {
            try {
                Class clz = Class.forName(eventServiceBeanDefinition.getBeanClassName());
                Annotation[] annotations = clz.getAnnotations();
                if (annotations.length == 1) {
                    Annotation serviceAnnotation = annotations[0];
                    return EventServiceBeanIdGeneratorEnum.getEventServiceBeanIdGeneraterEnum(serviceAnnotation.annotationType()).getBeanIds(eventServiceBeanDefinition, scanParam);
                } else {
                    throw new EventServiceException("先申明正确的注解");
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return new HashSet<>();
        }
    }
    /**
     * eventService beanId内部生成器,现有3类生成器
     */
    enum EventServiceBeanIdGeneratorEnum {

        /**
         * BillEventService注解beanid的生成器
         */
        BillEventServiceBeanIdGenerator(BillEventService.class) {
            @Override
            public Set<String> getBeanIds(BeanDefinition eventServiceBeanDefinition, ScanParam scanParam) {
                //获取service
                Class handlerClass = getHandlerClass(eventServiceBeanDefinition);
                Set<String> beanIds = new HashSet<>();
                //获取services上的注解
                BillEventService eventService = (BillEventService)handlerClass.getAnnotation(BillEventService.class);
                Set<String> billDefineIds = new HashSet<>();
                //如果支持befineid模式,分解billdefineid
                if (scanParam.getBillEventSupportType() == BillEventSupportType.ALL || scanParam.getBillEventSupportType() == BillEventSupportType.DEFINEID) {
                    String[] arr = eventService.billDefineId().split(",");
                    billDefineIds.addAll(Arrays.asList(arr));
                }
                //拿到类上的泛型注解
                Type[] types = handlerClass.getGenericInterfaces();
                if (types.length > 0) {//如果实现的是EventHandler接口
                    //得到泛型的具体类
                    Type type = types[0];
                    if (type != null) {
                        for (String billDefineId : billDefineIds) {
                            beanIds.add(getGenericEventClassName(type) + billDefineId);
                        }
                        //支持befinecode
                        if (scanParam.getBillEventSupportType() == BillEventSupportType.ALL || scanParam.getBillEventSupportType() == BillEventSupportType.DEFINECODE) {
                            String[] arr = eventService.billDefineCode().split(",");
                            for (String billDefineCode : arr) {
                                DefineCodeBeanDefinitionRegistrarContext.addDefineCodeBeanDefinition(getGenericEventClassName(type), billDefineCode, eventServiceBeanDefinition);
                            }
                        }
                    }
                } else {//如果实现的是AbstractEventHandler抽象类
                    Type type = handlerClass.getGenericSuperclass();
                    if (type != null) {
                        //得到泛型的具体类
                        for (String billDefineId : billDefineIds) {
                            beanIds.add(getGenericEventClassName(type) + billDefineId);
                        }
                        //支持befinecode
                        if (scanParam.getBillEventSupportType() == BillEventSupportType.ALL || scanParam.getBillEventSupportType() == BillEventSupportType.DEFINECODE) {
                            String[] arr = eventService.billDefineCode().split(",");
                            for (String billDefineCode : arr) {
                                DefineCodeBeanDefinitionRegistrarContext.addDefineCodeBeanDefinition(getGenericEventClassName(type), billDefineCode, eventServiceBeanDefinition);
                            }
                        }
                    }
                }
                return beanIds;
            }
        },
        /**
         * WfEventService注解beanid的生成器
         */
        WfEventServiceBeanIdGenerator(WfEventService.class) {
            @Override
            public Set<String> getBeanIds(BeanDefinition eventServiceBeanDefinition, ScanParam scanParam) {
                //获取service
                Class handlerClass = getHandlerClass(eventServiceBeanDefinition);
                WfEventService eventService = (WfEventService)handlerClass.getAnnotation(WfEventService.class);
                Set<String> beanIds = new HashSet<>();
                //支持befineid
                if (scanParam.getBillEventSupportType() == BillEventSupportType.ALL || scanParam.getBillEventSupportType() == BillEventSupportType.DEFINEID) {
                    String[] billDefineIds = eventService.billDefineId().split(",");
                    for (String billDefineId : billDefineIds) {
                        beanIds.add(eventService.eventType().name()  + billDefineId);
                    }
                }
                //支持befinecode
                if (scanParam.getBillEventSupportType() == BillEventSupportType.ALL || scanParam.getBillEventSupportType() == BillEventSupportType.DEFINECODE) {
                    String[] arr = eventService.billDefineCode().split(",");
                    for (String billDefineCode : arr) {
                        DefineCodeBeanDefinitionRegistrarContext.addDefineCodeBeanDefinition(eventService.eventType().name(), billDefineCode, eventServiceBeanDefinition);
                    }
                }
                return beanIds;
            }
        },
        /**
         * BoEventService注解beanid的生成器
         */
        BoEventServiceBeanIdGenerator(BoEventService.class) {
            @Override
            public Set<String> getBeanIds(BeanDefinition eventServiceBeanDefinition, ScanParam scanParam) {
                //获取service
                Class handlerClass = getHandlerClass(eventServiceBeanDefinition);
                BoEventService eventService = (BoEventService)handlerClass.getAnnotation(BoEventService.class);
                Set<String> beanIds = new HashSet<>();
                String[] boDefineIds = eventService.boDefineId().split(",");
                for (String boDefineId : boDefineIds) {
                    beanIds.add(boDefineId);
                }
                return beanIds;
            }
        };

        //处理类上的注解class
        private Class eventServiceClass;

        EventServiceBeanIdGeneratorEnum(Class eventServiceClass) {
            this.eventServiceClass = eventServiceClass;
        }

        /**
         * 生成BeanDefinition的beanId
         * @param eventServiceBeanDefinition
         * @return
         */
        protected abstract Set<String> getBeanIds(BeanDefinition eventServiceBeanDefinition, ScanParam scanParam);

        private Class getEventServiceClass() {
            return eventServiceClass;
        }

        /**
         * 根据serviceclass获取beanid的生成器
         * @param eventServiceClass
         * @return
         */
        private static EventServiceBeanIdGeneratorEnum getEventServiceBeanIdGeneraterEnum(Class eventServiceClass) {
            for (EventServiceBeanIdGeneratorEnum item : EventServiceBeanIdGeneratorEnum.values()) {
                if (item.getEventServiceClass() == eventServiceClass) {
                    return item;
                }
            }
            return null;
        }

        private static Class getHandlerClass(BeanDefinition eventServiceBeanDefinition) {
            Class handlerClass = null;
            try {
                handlerClass = Class.forName(eventServiceBeanDefinition.getBeanClassName());
            } catch (ClassNotFoundException e) {
                throw new EventServiceException(e.getMessage());
            }
            return handlerClass;
        }

        /**
         * 获取泛型上类名
         * @param type
         * @return
         */
        private static String getGenericEventClassName(Type type) {
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType)type;
                Type[] actualTypeArgumentTypes = parameterizedType.getActualTypeArguments();
                if (actualTypeArgumentTypes.length == 1) {
                    Type actualTypeArgumentType = actualTypeArgumentTypes[0];
                    Class clz = null;
                    try {
                        clz = Class.forName(actualTypeArgumentType.getTypeName());
                    } catch (ClassNotFoundException e) {
                        throw new EventServiceException(e.getMessage());
                    }
                    //泛型参数是为ApplicationEvent
                    if (ApplicationEvent.class.isAssignableFrom(clz)) {
                        return firstChar2LowerCase(actualTypeArgumentType.getTypeName());
                    } else {
                        throw new EventServiceException("不支持的泛型事件");
                    }
                } else {
                    throw new EventServiceException("不支持的泛型事件");
                }
            }
            throw new EventServiceException("不支持的泛型事件");
        }

        /**
         * 包名取最后.的字母,并且首字母小写
         * @param str
         * @return
         */
        private static String firstChar2LowerCase(String str) {
            String lastStr = str.substring(str.lastIndexOf(".") + 1);
            return lastStr.substring(0, 1).toLowerCase() + lastStr.substring(1);
        }

    }
}
/**
 * 核心BeanDefinition的注入
 */
class CoreBeanDefinitionRegistrarContext {

    /**
     * 注入3类核心BeanDefinition
     * @param beanDefinitionRegistry
     */
    public static void register(BeanDefinitionRegistry beanDefinitionRegistry) {
        //注入流程的监听
        registerWfEventListener(beanDefinitionRegistry);
        //注入单据的监听
        registerBillEventListeners(beanDefinitionRegistry);
        //注入ImportEventServiceDefineCodeRegistrar
        registerEventServiceDefineCodeRegistrar(beanDefinitionRegistry);
    }

    private static void registerWfEventListener(BeanDefinitionRegistry beanDefinitionRegistry) {
        registerWfEventListener(EndInstanceWFEventListener.class, WFEventType.END_INSTANCE, beanDefinitionRegistry);
        registerWfEventListener(EnterNodeWfEventListener.class, WFEventType.ENTER_NODE, beanDefinitionRegistry);
        registerWfEventListener(LeaveNodeWFEventListener.class, WFEventType.LEAVE_NODE, beanDefinitionRegistry);
        registerWfEventListener(TaskAssignWfEventListener.class, WFEventType.TASK_ASSIGN, beanDefinitionRegistry);
    }

    /**
     * 利用javassist动态的给类加上WFGlobalListener注解
     * @param listenerClass
     * @param wfEventType
     * @param beanDefinitionRegistry
     */
    private static void registerWfEventListener(Class listenerClass, WFEventType wfEventType, BeanDefinitionRegistry beanDefinitionRegistry) {
        try {
            CtClass ctClass = ClassPool.getDefault().makeClass(listenerClass.getName());
            //设置别名,一个jvm只是存在一个名字的一个对象
            ctClass.setName(listenerClass.getName() + "$" + wfEventType.name());
            ConstPool constPool = ctClass.getClassFile().getConstPool();
            AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
            javassist.bytecode.annotation.Annotation listenerAnnotation = new javassist.bytecode.annotation.Annotation(WFGlobalListener.class.getCanonicalName(), constPool);
            EnumMemberValue enumMemberValue = new EnumMemberValue(constPool);
            enumMemberValue.setType(WFEventType.class.getName());
            enumMemberValue.setValue(wfEventType.name());
            listenerAnnotation.addMemberValue("eventType", enumMemberValue);
            annotationsAttribute.addAnnotation(listenerAnnotation);
            ctClass.getClassFile().addAttribute(annotationsAttribute);
            Class clz = ctClass.toClass();
            BeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClassName(clz.getName());
            beanDefinitionRegistry.registerBeanDefinition("wfEventListener$"  + clz.getSimpleName(), beanDefinition);
        } catch (CannotCompileException e) {
            throw new EventServiceException(e.getMessage());
        }
    }

    private static void registerBillEventListeners(BeanDefinitionRegistry beanDefinitionRegistry) {
        registerClass(BillAfterCommitEventListener.class, beanDefinitionRegistry);
        registerClass(BillAfterDeleteEventListener.class, beanDefinitionRegistry);
        registerClass(BillAfterSaveEventListener.class, beanDefinitionRegistry);
        registerClass(BillAfterValueChangeEventListener.class, beanDefinitionRegistry);
        registerClass(BillBeforeSaveEventListener.class, beanDefinitionRegistry);
    }

    private static void registerClass(Class clz, BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClassName(clz.getName());
        beanDefinitionRegistry.registerBeanDefinition("billEventListener$"  + clz.getSimpleName(), beanDefinition);

    }

    /**
     * 注入definecode的处理
     * @param beanDefinitionRegistry
     */
    private static void registerEventServiceDefineCodeRegistrar(BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClassName(ImportEventServiceDefineCodeRegistrar.class.getName());
        beanDefinitionRegistry.registerBeanDefinition("importEventServiceDefineCodeRegistrar", beanDefinition);
    }

}

class DefineCodeBeanDefinitionRegistrarContext {

    private static BeanDefinitionRegistry beanDefinitionRegistry;

    private static List<DefineCodeBeanDefinition> defineCodeBeanDefinitions = new ArrayList<>();

    public static void setBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        beanDefinitionRegistry = registry;
    }

    public static void addDefineCodeBeanDefinition(String prefix, String defineCode, BeanDefinition beanDefinition) {
        defineCodeBeanDefinitions.add(new DefineCodeBeanDefinition(prefix, defineCode, beanDefinition));
    }

    public static void registerBeanDefinition() {
        for (DefineCodeBeanDefinition defineCodeBeanDefinition : defineCodeBeanDefinitions) {
            //获取beanId
            String beanId = defineCodeBeanDefinition.getPrefix() + defineCode2Id(defineCodeBeanDefinition.getDefineCode());
            if (beanDefinitionRegistry.containsBeanDefinition(beanId)) {
                throw new EventServiceException(beanId + "在spring容器中已经存在");
            }
            //放入spring容器
            beanDefinitionRegistry.registerBeanDefinition(beanId, defineCodeBeanDefinition.getBeanDefinition());
        }
    }

    /**
     * 查询t_bill_type,把definecode转为defineid
     * @param defineCode
     * @return
     */
    private static String defineCode2Id(String defineCode) {
        return BaseObjectIdUtil.getBillDefineIdByCode(defineCode);
    }

    static class DefineCodeBeanDefinition {
        //前缀=提交事件名或流程事件名
        private String prefix;
        private String defineCode;
        private BeanDefinition beanDefinition;

        public DefineCodeBeanDefinition(String prefix, String defineCode, BeanDefinition beanDefinition) {
            this.prefix = prefix;
            this.defineCode = defineCode;
            this.beanDefinition = beanDefinition;
        }

        public String getPrefix() {
            return prefix;
        }

        public String getDefineCode() {
            return defineCode;
        }

        public BeanDefinition getBeanDefinition() {
            return beanDefinition;
        }
    }
}

/**
 * definecode注入,实现原理:在spring实例化所有bean后,启动前,调用dao层把definecode转化为defineid
 * 为什么这么做:dao层在加载bean时,还没有加载到spring容器,无法被调用
 */
public class ImportEventServiceDefineCodeRegistrar implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        DefineCodeBeanDefinitionRegistrarContext.registerBeanDefinition();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值