1. 程式人生 > >cxf和spring整合注入值為NULL問題

cxf和spring整合注入值為NULL問題

用cxf+spring開發web service程式很簡單,不過有一些整合問題要注意。

1、關於bean的宣告 

要釋出或者要呼叫的web service介面,需要用@WebService註解宣告。不過要注意的是,@WebService註解不會把類宣告為spring的bean 

可以宣告為bean的方式有以下4個: 

<jaxws:endpoint> 
<jaxws:client> 
<bean id="" class=""> 
@Component 

寫了一個類來證明這一點: 

Java程式碼  收藏程式碼
  1. protected void doGet(HttpServletRequest request,  
  2.             HttpServletResponse response) throws ServletException, IOException {  
  3.         ServletContext context = request.getServletContext();  
  4.         WebApplicationContext wc = WebApplicationContextUtils  
  5.                 .getWebApplicationContext(context);  
  6.         String[] beans = wc.getBeanDefinitionNames();  
  7.         for (String beanName : beans) {  
  8.             System.out.println(beanName);  
  9.         }  
  10.         RemedyWebServiceCM remedy = (RemedyWebServiceCM) wc.getBean("remedy");  
  11.         AcknowledgeRequest message = new AcknowledgeRequest();  
  12.         remedy.acknowledge(message);  
  13.     }  

在控制檯可以看到以下幾個bean: 

20:02:24,120 INFO  [stdout] (http--0.0.0.0-8888-2) helloWorldImpl 
20:02:24,120 INFO  [stdout] (http--0.0.0.0-8888-2) helloWorld 
20:02:24,120 INFO  [stdout] (http--0.0.0.0-8888-2) remedy 

以上3個bean,就分別是由<bean>、<jaxws:endpoint>、<jaxws:client>生成的 

2、如果要在<jaxws:endpoint>的實現類中注入bean的話,要注意: 

錯誤的寫法: 
Xml程式碼  收藏程式碼
  1. <jaxws:endpoint id="helloWorld" address="/HelloWorld"  
  2.         implementor="com.huawei.framework.webservice.HelloWorldImpl" />  

用這種寫法,雖然HelloWorldImpl類已經被宣告成bean了,但是注入是失敗的 

準確來說,在spring容器中存在有HelloWorldImpl對應的bean,並且相關的依賴也已經注入了。但是cxf框架得到的HelloWorldImpl,與上述的bean不是同一個物件,這個HelloWorldImpl物件可能是用反射或者其他機制創建出來的,沒有任何元件被注入 

正確的寫法: 
Xml程式碼  收藏程式碼
  1. <jaxws:endpoint id="helloWorld" address="/HelloWorld"  
  2.         implementor="#helloWorldImpl" />  

在implementor屬性中,用#beanName,這樣的話,cxf框架得到的HelloWorldImpl,就是spring容器持有的那個bean。當然這有個前提,就是系統中已經存在這個bean。用<bean id="">或者@Component都是OK的,這裡支援註解 

3、上面說的是<jaxws:endpoint>,比較簡單。但是<jaxws:client>就比較麻煩 

我目前感覺,<jaxws:client>宣告的bean,沒辦法在別的bean裡用@Autowired注入,只能用<bean id="">的方式來注入 
Java程式碼  收藏程式碼
  1. @WebService  
  2. public interface RemedyWebServiceCM {  
  3.     RemedyResponse acknowledge(AcknowledgeRequest arg0);  
  4.     RemedyResponse close(CloseRequest arg0);  
  5.     RemedyResponse notify(NotifyRequest arg0);  
  6. }  

Java程式碼  收藏程式碼
  1. public class HelloWorldImpl implements HelloWorld {  
  2.     private RemedyWebServiceCM remedy;  
  3.     public String sayHi(User theUser) {  
  4.         AcknowledgeRequest message = new AcknowledgeRequest();  
  5.         remedy.acknowledge(message);  
  6.         return "Hello " + theUser.getName() + " ,your age is "  
  7.                 + theUser.getAge();  
  8.     }  
  9.     public void setRemedy(RemedyWebServiceCM remedy) {  
  10.         this.remedy = remedy;  
  11.     }  
  12. }  


用這種<bean id="">的方式就可以 
Java程式碼  收藏程式碼
  1. @Controller  
  2. public class HelloWorldImpl implements HelloWorld {  
  3.     @Autowired  
  4.     private RemedyWebServiceCM remedy;  
  5.     public String sayHi(User theUser) {  
  6.         AcknowledgeRequest message = new AcknowledgeRequest();  
  7.         remedy.acknowledge(message);  
  8.         return "Hello " + theUser.getName() + " ,your age is "  
  9.                 + theUser.getAge();  
  10.     }  
  11. }