使用dubbo注解@Service注册服务后使用aop或者申明式事物导致无法注册的问题解决办法
2017-05-26 14:14
417 查看
导致这个问题的主要原因有2个
1:JdkDynamicProxy导致获取到的class路径不正确无法通过包路径检查动态代理后的对象获取到的class都是 com.sun.proxy开头的
2:cglib代理后由于dubbo的@Service注解头没有标注@Inherited导致无法查找到注解
解决思路:
既然是由于代理对象导致无法获取到注解那么我的思路就是获取到被代理的对象
1:引入spring-aop依赖
2:使用AopUtils来判断是属于哪种代理并分别通过反射获取被代理的对象
判断方式改为判断被代理的对象
这样就可以使被代理的对象也能注册了,使用这种方式有个坏处就是要修改源码
所以我的方法是把AnnotationBean的代码copy过来然后修改然后new自己的类来规避这个问题
1:JdkDynamicProxy导致获取到的class路径不正确无法通过包路径检查动态代理后的对象获取到的class都是 com.sun.proxy开头的
private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } String beanClassName = bean.getClass().getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; }
2:cglib代理后由于dubbo的@Service注解头没有标注@Inherited导致无法查找到注解
Service service = bean.getClass().getAnnotation(Service.class);
解决思路:
既然是由于代理对象导致无法获取到注解那么我的思路就是获取到被代理的对象
1:引入spring-aop依赖
2:使用AopUtils来判断是属于哪种代理并分别通过反射获取被代理的对象
public class AopUtils { private static final Logger logger = LoggerFactory.getLogger(AopUtils.class); public static Object getTarget(Object bean){ if(org.springframework.aop.support.AopUtils.isCglibProxy(bean)) return getCglibAopObject(bean); if(org.springframework.aop.support.AopUtils.isAopProxy(bean)) return getJDKDynamicAopObject(bean); return bean; } private static Object getJDKDynamicAopObject(Object bean){ Field field = null; try { field = bean.getClass().getSuperclass().getDeclaredField("h"); field.setAccessible(true); AopProxy aopProxy = null; aopProxy = (AopProxy) field.get(bean); field.setAccessible(false); Field advised = aopProxy.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget(); advised.setAccessible(false); return target; } catch (Exception e) { logger.error("获取JDK动态代理真实对象出错",e); return bean; } } private static Object getCglibAopObject(Object bean){ Field field = null; try { field = bean.getClass().getDeclaredField("CGLIB$CALLBACK_0"); field.setAccessible(true); Object dynamicAdvisedInterceptor = field.get(bean); field.setAccessible(false); Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget(); advised.setAccessible(false); return target; } catch (Exception e) { logger.error("获取CGLIB动态代理真实对象出错",e); return bean; } } }
判断方式改为判断被代理的对象
Object unWrapBean = AopUtils.getTarget(bean); if (! isMatchPackage(unWrapBean)) { return bean; }
Service service = unWrapBean.getClass().getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if (unWrapBean.getClass().getInterfaces().length > 0) { serviceConfig.setInterface(unWrapBean.getClass().getInterfaces()[0]); } else { throw new IllegalStateException("Failed to export remote service class " + unWrapBean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); } }
这样就可以使被代理的对象也能注册了,使用这种方式有个坏处就是要修改源码
所以我的方法是把AnnotationBean的代码copy过来然后修改然后new自己的类来规避这个问题
@Bean public AnnotationBean annotationBean(@Value("${dubbo.annotation.package}") String packageName) { AnnotationBean annotationBean = new AnnotationBean(); annotationBean.setPackage(packageName); return annotationBean; }
相关文章推荐
- 【转】注册表问题导致usb设备或光驱无法使用的解决办法
- 使用Service描述的服务与springAop冲突导致服务无法暴露
- dubbo服务无法注册问题 Failed to subscribe consumer:// 解决方法
- 开机登录失败 提示"user profile service服务未能登录,无法加载用户配置文件" 问题解决办法
- 无法注册 URL http://+:8735/Service/。另一应用程序已使用 HTTP.SYS 注册了该 URL。的解决办法。
- 密钥发行中心(KDC)找不到相应的证书用于智能卡登录,或者无法验证 KDC 证书。如果不解决该问题,智能卡登录可能不会正常工作。若要更正该问题,请使用 certutil.exe 验证现有的 KDC 证书或注册新的 KDC 证书。
- linux下使用crontab无法启动tomcat服务问题解决办法
- 使用dwr同步调用导致无法获取js方法的返回结果问题的解决办法
- Jenkins遇到问题一:jenkins配置权限不对导致无法登陆或者空白页面解决办法
- dubbo使用的zookeeper注册中心客户端太多导致连不上解决办法|linux的arp限制
- 问题:Custom tool error: Failed to generate code for the service reference 'AppVot;结果:添加Service Reference, 无法为服务生成代码错误的解决办法
- R.id或者R.layout等等在使用时后面无法找找相应空间或者布局问题的解决办法
- 关于CSS中内层使用float导致外层的背景无法显示的问题的解决
- 使用 apt-get 的時候,出现目录或者被锁住的解决办法(E: 无法获得锁 /var/lib/dpkg/lock - open (11: 资源临时不可用) E: 无法对管理目录(/var/lib/dpkg/)加锁,是不是另一个包管理)
- Microsoft Office Word 2007 切换窗口后鼠标无法使用问题的解决办法
- [转载] Office2007切换窗口后鼠标无法使用问题的解决办法
- 关于CSS中内层使用float导致外层的背景无法显示的问题的解决方法
- Microsoft Office Word 2007 切换窗口后鼠标无法使用问题的解决办法
- 添加Service Reference, 无法为服务生成代码错误的解决办法
- liferay-tomcat注册服务的方法和之后产生的乱码问题的解决办法