概述
web.xml加载spring-mvc 和 spring-dubbo 配置文件
<context-param> <!-- 加载配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-dubbo.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置springMVC中央处理器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param> <!-- 加载配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 指定需要过滤的请求 Mapping 【/】 表示所有请求 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
上面的web.xml 把 spring-dubbo 的配置文件加入到了spring 容器中(根上下文),spingmvc 的配置文件被加入到springmvc容器中。关于Spring和springmvc父子容器的关系参考我的另一篇博文https://blog.csdn.net/liuhaiquan123521/article/details/94061017
Controller 代码如下
package com.kavin.consumer.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.alibaba.dubbo.config.annotation.Reference;
import com.kavin.api.UserService;
@Controller
public class UserController {
@Reference //使用dubbo提供的reference注解引用远程服务
private UserService userService;
@RequestMapping("/")
public String getUser() {
System.out.println(userService.sayHello("张三"));
return "index";
}
}
当@Reference 注解在 带有 @Controller 的类中使用的时候,默认@Controller的javaBean 被加载到SpringMVC容器中,因为spingmvc容器没有加载dubbo 的配置文件,而是被spring容器加载了,从而导致@Reference 在SpringMVC容器中不能被解析,所以被@Reference 修饰的远程服务变量不能被注入成功,才会使引用的服务为空。@Reference 相当于给Controller 去 Set 一个属性。
解决办法:
1.只将dubbo服务注入到service和Repository中而不是Controller中,其实大部分时候都可如此
(先提此时件是spring容器加载dubbo配置文件和spring扫包的配置文件。springmvc 加载springmvc 的配置文件。并且spring扫描service层、dao层的javaBean,而springMVC 扫描Controller层的javaBean,包路径不重叠,避免spring加载了一遍,springmvc又重复加载一遍。
因为spring容器先加载指定包下的bean,此时的dubbo注解能被识别,(因为spring容器加载了dubbo 的配置文件,所以能识别dubbo 注解)然后注入进来。当springmvc 扫包的路径和spring容器扫包的路径一致时。则会重新加载这个包路径下的JavaBean 到springmvc容器中。但是此时springmvc容器中并没有加载dubbo的配置文件,所以无法识别dubbo 的注解,因此注入失败,出现NULL的情况)
2.去掉web.xml中listener,将全部配置文件都放到springmvc中加载,这样只生成一个上下文。
3.在spring-mvc.xml也加入duboo的配置,这样虽然有了冗余,但是可以保证两个上下文。
我采用第二种方式解决。 将上面的web,xml 改成下面的web,xml
去掉了listener 和 context-param。让springmvc加载dubbo的配置文件。因。为spring-mvc 和spring-dubbo 都是 以spring开头的。并且在spring目录下。所以修改init-param 中的
param-value 为classpath:spring/spring-*.xml
<!-- 配置springMVC中央处理器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param> <!-- 加载dubbo 和 mvc的配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 指定需要过滤的请求 Mapping 【/】 表示所有请求 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这个问题主要是考验了spring容器和springmvc容器的区别。之前我以为他俩是一个容器,后来翻阅好多文章之后才发现他俩是父子容器关系。因为Controller 在springmvc容器中被注入,而只有spring-dubbo文件加载到springmvc 中。springmvc容器才可以解析@Reference 注解,才能注入成功。否则Springmvc 容器在注册Controller 这个javaBean 的时候,发现@Reference这个注解无法解析,属性也随之注入失败。
。
最后
以上就是可靠蓝天为你收集整理的解决dubbo 中的 @Reference 引用远程服务为空。的全部内容,希望文章能够帮你解决解决dubbo 中的 @Reference 引用远程服务为空。所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复