Dubbo無法發佈被事務代理的Service問題

前言

在使用註解式dubbo開發的過程中,忽然發現Service上只要有@transactional註解或者是配置的事務切面時,該Service不能被dubbo發佈。

問題詳情

dubbo的配置:

  1. <span style="white-space:pre">    </span><!-- 定義註冊中心,採用zookeeper -->  
  2.     <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>  
  3.     <!-- 定義協議爲dubbo,在端口20880上暴露服務 -->  
  4.     <dubbo:protocol name="dubbo" port="20880"/>  
  5.     <dubbo:annotation package="com.rondo"/>  
<span style="white-space:pre">	</span><!-- 定義註冊中心,採用zookeeper -->
	<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
	<!-- 定義協議爲dubbo,在端口20880上暴露服務 -->
	<dubbo:protocol name="dubbo" port="20880"/>
	<dubbo:annotation package="com.rondo"/>
事務的配置:

  1. <span style="white-space:pre">    </span><!-- 註解方式配置事務 -->  
  2.     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  3.         <property name="dataSource" ref="dataSource"/>  
  4.     </bean>  
  5.     <span style="white-space:pre">    </span><tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>  
<span style="white-space:pre">	</span><!-- 註解方式配置事務 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
    <span style="white-space:pre">	</span><tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
  1. @Component  
  2. @Service//這個service註解是dubbo的  
  3. @Transactional  
  4. public class UserServiceImpl implements UserService {  
  5.   
  6.     @Autowired  
  7.     private UserMapper userMapper;  
  8.   
  9.     @Override  
  10.     public Mapper<User> getMapper() {  
  11.         return userMapper;  
  12.     }  
  13. }  
@Component
@Service//這個service註解是dubbo的
@Transactional
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;

	@Override
	public Mapper<User> getMapper() {
		return userMapper;
	}
}

這種情況下,UserService不能被dubbo發佈。

解決思路

這個問題簡直~~,後來發現,在使用事務的時候,配置文件中使用了cglib的方式(proxy-target-class="true")爲service生成代理,而當dubbo掃描註解的時候,這個被代理的UserService並沒有dubbo的@service註解,因爲dubbo定義這個註解的時候,沒有允許子類集成父類的註解。

cglib生成代理的方式恰好是生成該類的子類,那麼問題顯而易見了,就是這個代理上缺少了@Service,怎麼解決這個問題呢?------------修改dubbo源碼是個好辦法,讓@service可以被子類繼承。

解決方法

1.https://github.com/alibaba/dubbo上有dubbo的源碼,找到dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/annotation/Service.java,複製裏面所有內容。

2.新建一個txt文件並修改名稱爲“Service.java”,打開粘貼所有內容,並添加註解@Inherited,別忘了導入Inherited的包,如圖:

3.javac Service.java將該java文件編譯爲class,具體步驟就不用說了吧。。。

4.使用解壓軟件打開dubbo-x.x.x.jar,找到包com.alibaba.dubbo.config.annotation下的Service.class,用自己編譯的替換掉原有的。

效果

做完上面這些,我覺得問題肯定解決了,於是重新啓動了一下工程,結果消費端調用UserService中的方法的時候還是會報沒有provider!word 天~,這怎麼可能!於是我啓動了dubbo-admin(關於這個玩意如果有疑問自己網上下載個dubbo-admin.war,你就明白了),在查看發佈的接口的時候發現悲劇了

我原本要發佈的UserService,竟然是SpringProxy。發現dubbo的@Service註解中有一個屬性“interfaceName”,這下問題得到徹底解決,將UserServiceImpl中的@Service註解修改爲@Service(interfaceName="com.rondo.business.service.UserService"),即指定了接口名稱,效果如圖:


然後,在消費端調用了一下,調用成功,而且事務也是有效的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章