技术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();
}
}