ROP扫描服务方法因桥方法产生的BUG的解决

本文介绍了ROP框架在扫描服务方法时遇到的问题,即Java泛型导致的桥方法被误识别,进而覆盖了真实的服务方法。文章详细分析了问题原因,并提出了相应的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ROP的服务类通过@ServiceMethodBean进行注解,服务方法通过@ServiceMethod标注,ROP在启动时自动扫描Spring容器中的Bean,将服务方法写到服务注册表中.

最近发现了一个问题,是由于Java泛型的桥方法和合成方法引起的,下面举例说明:

package com.rop.session;

/**
* 其中T是登录请求的类,而R是注销请求的类
* @author : chenxh
* @date: 13-10-16
*/

import com.rop.RopRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;

public abstract class AuthenticationService<T extends RopRequest,R extends RopRequest> {
...
public abstract Object logon(T logonRequest);


/**
* 该方法在子类在实现,并打上@ServiceMethod注解,作为注销的服务方法
* @param loginRequest
* @return
*/
public abstract Object logout(R logoutRequest);

}


AuthenticationService定义了两个抽象方法,需要子类实现,以便实现登录认证.

子类实现如下:

@ServiceMethodBean
public class AppAuthenticationService extends AuthenticationService<LogonRequest,LogoutRequest> {

public static final String USER_LOGON = "user.logon";
public static final String USER_LOGOUT = "user.logout";

...

@ServiceMethod(method = USER_LOGON, version = "1.0",
needInSession = NeedInSessionType.NO,ignoreSign = IgnoreSignType.YES)
@Override
public Object logon(LogonRequest logonRequest) {
...
}

@ServiceMethod(method = USER_LOGOUT, version = "1.0")
@Override
public Object logout(LogoutRequest logoutRequest) {
...
}
}


AppAuthenticationService类中覆盖了抽象父类中的方法,并且对泛型进行了具化.

但是当ROP扫描服务方法时,服务方法的入参识别发生了错误,错将入参识别为RopRequest,而非
LogonRequest,LogoutRequest.

断点跟踪到注册服务方法时,发现AuthenticationService类居然有2个logon和2个logout方法:

[img]http://dl2.iteye.com/upload/attachment/0090/2686/6747682c-f438-3c4b-8536-3b54829fccc6.jpg[/img]

1.logon(LogonRequest r)
2.logout(LogoutRequest r)

3.logon(RopRequest r)
4.logout(RopRequest r)

其中前两个方法是AuthenticationService中定义的方法,而后两个方法是为了实现泛型具化JAVA自动生产的方法,称为桥方法,可参见这篇文章的说明:
[url]http://jiangshuiy.iteye.com/blog/1339105[/url]

后两个方法也有和前两个方法一样的@ServiceMethod注解,因此在ROP扫描时,就可以扫描到桥方法,而把真正的方法覆盖了.

JAVA的Method反射类中拥有判断是否是桥方法的方法:
Method#isBridge()


前两个方法返回的是false,而后两个方法返回的是true.

另外,桥方法也是合成方法(Synthetic),Method反射类中拥有判断是否是桥方法的方法:
Method#isSynthetic()


关于合成方法,亦请参考[url]http://jiangshuiy.iteye.com/blog/1339105[/url]

为了避免ROP扫描到这些杂攻杂八的方法,因此ROP扫描程序做了以下的调整:

private void registerFromContext(final ApplicationContext context) throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("对Spring上下文中的Bean进行扫描,查找ROP服务方法: " + context);
}
String[] beanNames = context.getBeanNamesForType(Object.class);
for (final String beanName : beanNames) {
Class<?> handlerType = context.getType(beanName);

//1只对标注 ServiceMethodBean的Bean进行扫描
if(AnnotationUtils.findAnnotation(handlerType,ServiceMethodBean.class) != null){
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(method);
... }
},
new ReflectionUtils.MethodFilter() {
public boolean matches(Method method) {

//2不是合成方法,且标注了ServiceMethod的方法!!
return !method.isSynthetic() && AnnotationUtils.findAnnotation(method, ServiceMethod.class) != null;
}
}
);
}
}
...
}

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值