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

原创
2015/08/21 13:53
阅读数 154

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

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

Java代码  收藏代码

  1. package com.rop.session;  

  2.   

  3. /** 

  4.  * 其中T是登录请求的类,而R是注销请求的类 

  5.  * @author : chenxh 

  6.  * @date: 13-10-16 

  7.  */  

  8.   

  9. import com.rop.RopRequest;  

  10. import org.slf4j.Logger;  

  11. import org.slf4j.LoggerFactory;  

  12.   

  13. import java.util.UUID;  

  14.   

  15. public abstract class AuthenticationService<T extends RopRequest,R extends RopRequest> {  

  16.     ...  

  17.     public abstract  Object logon(T logonRequest);  

  18.   

  19.   

  20.     /** 

  21.      * 该方法在子类在实现,并打上@ServiceMethod注解,作为注销的服务方法 

  22.      * @param loginRequest 

  23.      * @return 

  24.      */  

  25.     public abstract Object logout(R logoutRequest);  

  26.   

  27. }  



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

子类实现如下: 

Java代码  收藏代码

  1. @ServiceMethodBean  

  2. public class AppAuthenticationService extends AuthenticationService<LogonRequest,LogoutRequest> {  

  3.   

  4.     public static final String USER_LOGON = "user.logon";  

  5.     public static final String USER_LOGOUT = "user.logout";  

  6.   

  7.     ...  

  8.   

  9.     @ServiceMethod(method = USER_LOGON, version = "1.0",  

  10.                   needInSession = NeedInSessionType.NO,ignoreSign = IgnoreSignType.YES)  

  11.     @Override  

  12.     public Object logon(LogonRequest logonRequest) {  

  13.          ...  

  14.     }  

  15.   

  16.     @ServiceMethod(method = USER_LOGOUT, version = "1.0")  

  17.     @Override  

  18.     public Object logout(LogoutRequest logoutRequest) {  

  19.         ...  

  20.     }  

  21. }  



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

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

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



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

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

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

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

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

Java代码  收藏代码

  1. Method#isBridge()  



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

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

Java代码  收藏代码

  1. Method#isSynthetic()  



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

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

Java代码  收藏代码

  1.     private void registerFromContext(final ApplicationContext context) throws BeansException {  

  2.         if (logger.isDebugEnabled()) {  

  3.             logger.debug("对Spring上下文中的Bean进行扫描,查找ROP服务方法: " + context);  

  4.         }  

  5.         String[] beanNames = context.getBeanNamesForType(Object.class);  

  6.         for (final String beanName : beanNames) {  

  7.             Class<?> handlerType = context.getType(beanName);  

  8.              

  9.           //1只对标注 ServiceMethodBean的Bean进行扫描  

  10.             if(AnnotationUtils.findAnnotation(handlerType,ServiceMethodBean.class) != null){  

  11.                 ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {  

  12.                             public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {  

  13.                                 ReflectionUtils.makeAccessible(method);  

  14. ...                            }  

  15.                         },  

  16.                         new ReflectionUtils.MethodFilter() {  

  17.                             public boolean matches(Method method) {  

  18.                               

  19.                                 //2不是合成方法,且标注了ServiceMethod的方法!!  

  20.                                 return !method.isSynthetic() && AnnotationUtils.findAnnotation(method, ServiceMethod.class) != null;  

  21.                             }  

  22.                         }  

  23.                 );  

  24.             }  

  25.         }  

  26. ...  

  27.     }  


展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部