Jarslink应用示例-----注解方式

我们可以从下面的代码中看到Jarslink扫描Action是从已经加载的ApplicationContext中获取指定的bean中加载,我们可以通过我们的自定义注解的方式加在每个模块需要通信的类上面实现分发请求的功能。

/**
* 请求类注解
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ActionClass {
     String value();
     String name();
}
/**
 * 请求方法注解
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActionMethod {
    String value();

    String name();

    String description() default "";
}

对于上面的两个注解,我个人倾向于将他们理解为spring中的@Controller和@XXMapping的关系,接下来我们来看jarslink中是如何扫描到对应注解的

    private Map<String, com.alipay.jarslink.api.ActionMethod> scanActions(ApplicationContext applicationContext, Class<ActionClass> type){
        Map<String, com.alipay.jarslink.api.ActionMethod> actions = Maps.newHashMap();
        //获取Spring容器内的ActionService类
        for (Object action : applicationContext.getBeansWithAnnotation(type).values()) {
            Object target=null;
            //获取代理对象的目标对象
            try {
                target= AopTargetUtils.getTarget(action);
            } catch (Exception e) {
                throw new ModuleRuntimeException("JarsLink scanActions actionName is null");
            }
            //获取url第一层路径
            String actionValue = target.getClass().getAnnotation(type).value();
            //获取方法名称
            String actionName=target.getClass().getAnnotation(type).name();
//            if (isBlank(actionValue)) {
//                throw new ModuleRuntimeException("JarsLink scanActions value is null");
//            }
            if (isBlank(actionName)) {
                throw new ModuleRuntimeException("JarsLink "+actionValue+" scanActions name is null");
            }

            //添加actionClassEntity信息(此处忽略存储对应实体信息过程)

            //获取ActionClass注解的类中所有方法
            Method[] methods=target.getClass().getMethods();
            List<ActionMethodEntity> actionMethodEntityList=new ArrayList<>();
            for(Method method:methods){
                //如果方法使用了ActionMethod添加的注解则需要被暴露出去的接口
                Annotation annotation=method.getAnnotation(ActionMethod.class);
                if(annotation instanceof ActionMethod){
                    //通过注解获取method基本信息
                    String methodValue=((ActionMethod) annotation).value();
                    String methodName=((ActionMethod)annotation).name();
                    String methodDescription=((ActionMethod)annotation).description();
                    if (isBlank(methodValue)) {
                        throw new ModuleRuntimeException("JarsLink scanActions methodValue is null");
                    }
                    if (isBlank(methodName)) {
                        throw new ModuleRuntimeException("JarsLink "+methodValue+" scanActions methodName is null");
                    }

                    //添加ActionMethod信息(此处忽略存储ActionMethod实体过程)
                    String key;
                  if(actionValue.equalsIgnoreCase("/")||actionValue.equalsIgnoreCase("")){
                        key=methodValue.toUpperCase(Locale.CHINESE);
                    }else{
                        key=(actionValue+"/"+methodValue).toUpperCase(Locale.CHINESE);
                    }
                    //将路由/actionService/actionMethod 映射到类对象,方法对象上,便于反射调用
                    actions.put(key, actionMethod);
                }
            }
        }
        return actions;
    }

扫描到对应的类和方法后,将类和方法的value值映射为唯一路由,后期实现通过路由获取对应的Action来进行反射调用。

protected <R, T> T doActionWithinModuleClassLoader(com.alipay.jarslink.api.ActionMethod actionMethod, R actionRequest) {
        checkNotNull(actionMethod, "action is null");
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            ClassLoader moduleClassLoader = actionMethod.getAction().getClass().getClassLoader();
            Thread.currentThread().setContextClassLoader(moduleClassLoader);
            if(actionRequest==null){
                Method method= BeanUtils.findMethod(actionMethod.getAction().getClass(),actionMethod.getMethod().getName());
                return (T) method.invoke(actionMethod.getAction());
            }
            Method method=null;
            if(actionRequest instanceof String){
                method= BeanUtils.findMethod(actionMethod.getAction().getClass(),actionMethod.getMethod().getName(),String.class);
            }else if(actionRequest instanceof Map){
                method= BeanUtils.findMethod(actionMethod.getAction().getClass(),actionMethod.getMethod().getName(),Map.class);
            }
            return (T) method.invoke(actionMethod.getAction(),actionRequest);
        } catch (Exception e) {
            LOGGER.error("调用模块出现异常,action=" + actionMethod, e);
            throw new ModuleRuntimeException("doActionWithinModuleClassLoader has error,action=" + actionMethod, e);
        } finally {
            Thread.currentThread().setContextClassLoader(classLoader);
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值