ROP掃描服務方法因橋方法產生的BUG的解決

ROP的服務類經過@ServiceMethodBean進行註解,服務方法經過@ServiceMethod標註,ROP在啓動時自動掃描Spring容器中的Bean,將服務方法寫到服務註冊表中. 

最近發現了一個問題,是因爲Java泛型的橋方法和合成方法引發的,下面舉例說明: 
java

Java代碼  收藏代碼session

  1. package com.rop.session;  ide

  2.   

  3. /** ui

  4.  * 其中T是登陸請求的類,而R是註銷請求的類 spa

  5.  * @author : chenxh debug

  6.  * @date: 13-10-16 blog

  7.  */  圖片

  8.   

  9. import com.rop.RopRequest;  get

  10. import org.slf4j.Logger;  it

  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.     }  

相關文章
相關標籤/搜索