`
fly0wings
  • 浏览: 34808 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring的xml配置与annotation注解混合使用无法Autowired的问题

 
阅读更多

问题:

在LVMMCrawlerSuit.java是xml配置的bean, 需要注入用@Component声明的bean. 但是运行的时候却报NullPointerException. 说明没有注入进来.

 

代码:

1. java

Java代码  收藏代码
  1. 1. LVMMCrawlerSuit.java  
  2.  public class LVMMCrawlerSuit extends AbstractCrawlerSuit{  
  3.   
  4.     @Resource  
  5.     private LVMMURLBuilder lvmmurlBuilder;  
  6.   
  7.     public LVMMCrawlerSuit() {  
  8.     }  
  9. }  
  10.   
  11. 2. LVMMURLBuilder.java  
  12. @Component  
  13. public class LVMMURLBuilder extends AbstractResourceURLBuilder {  
  14.     public LVMMURLBuilder() {    }  
  15. }  

 

2. 配置.

Xml代码  收藏代码
  1. <bean id="LVMMCrawlerSuit" class = 'com.qunar.b2c.crawlersuit.impl.LVMMCrawlerSuit'/>   

 

问题查找:

1. 查找网上资源,未果.

2. 果断debug,跟踪源码.

       将断点定位到 org.springframework.context.support.AbstractRefreshableApplicationContext#loadBeanDefinitions ,该方法是加载bean的必经之路.跟踪发现,该方法共执行两次,生成了两个不同的 org.springframework.beans.factory.support.DefaultListableBeanFactory, 并且后者的parentBeanFactory为前者,根据原设计是后者可以调用前者的bean 并完成注入.

      现在报NullPointerException,很明显是"父调用子",所以肯定拿不到.在打印的log中进行了佐证.

      在debug中发现,两次执行分别来自不同的beans资源文件: app-web.xml 和 applicationContext-*.xml, 按key查找,很容易找到了配置信息如下.

Xml代码  收藏代码
  1. <servlet>  
  2.         <servlet-name>dispatcherServlet</servlet-name>  
  3.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.         <init-param>  
  5.             <param-name>contextConfigLocation</param-name>  
  6.             <param-value>  
  7.                 classpath:classpath:app-web.xml  
  8.             </param-value>  
  9.         </init-param>  
  10.         <load-on-startup>1</load-on-startup>  
  11.     </servlet>  
  12.   
  13.         <context-param>  
  14.         <param-name>contextConfigLocation</param-name>  
  15.         <param-value>classpath:applicationContext-*.xml</param-value>  
  16.     </context-param>  

 

    既然,两次加载,并且加载了不同的beans,虽然有父子的层级关系,但是限制多多. 那么就尝试合二为一.

    在test中,发现因为修改了spring默认加载的文件名,所以删除任何一个配置都不能正确运行.那么就全部设置成一样的吧. test success......

 

解决方案:

    方案一. 将配置文件路径合并, 分别指定给不同配置.

Xml代码  收藏代码
  1. <servlet>  
  2.         <servlet-name>dispatcherServlet</servlet-name>  
  3.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.         <init-param>  
  5.             <param-name>contextConfigLocation</param-name>  
  6.             <param-value>  
  7.                 classpath:applicationContext-*.xml,classpath:app-web.xml  
  8.             </param-value>  
  9.         </init-param>  
  10.         <load-on-startup>1</load-on-startup>  
  11.     </servlet>  
  12.   
  13.         <context-param>  
  14.         <param-name>contextConfigLocation</param-name>  
  15.         <param-value>classpath:applicationContext-*.xml,classpath:app-web.xml</param-value>  
  16.     </context-param>  

 

 

    方案二. 原有配置不变,合理规划Bean的定义及合理使用.

         在方案一中, 使用的简单,粗暴的解决办法. 没有考虑到spring的设计思想. 既然有ioc容器的父子级划分,那么在使用的时候,一定会有用的.

         在使用annotation定义bean 的时候,是需要增加如下代码,对使用何种注解的类才管理到ioc容器中.

 

Xml代码  收藏代码
  1. <context:component-scan base-package="com.qunar.b2c">  
  2.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />  
  3.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />  
  4.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />  
  5.        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />  
  6.    </context:component-scan>  

 

        上述提到, 在 spring web的使用中, 会加载两个ioc容器,

          1. 一个是contextConfigLocation定义,用来启动spring核心框架的. 所以在该步骤中,应加载应用中的基础服务信息的bean,如 dao,Service 等等.

          2. 另外一个ioc容器是web加载的容器, 那么只需加载Controller相关的bean.

        因为在spring ioc的 DefaultListableBeanFactory类是支持父子关系,

            1. 子容器是可以访问到父容器中的bean,

            2. 然而父容器访问不了子容器的bean,

        这就保证了, Controller可以访问 Service等, 但是Service 访问不了web层的bean, 这样就将职责分开了.所以修改的配置如下:

 

Xml代码  收藏代码
  1. applicationContext-beans.xml:  
  2.   
  3. <context:component-scan base-package="com.qunar.b2c">  
  4.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />  
  5.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />  
  6.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />  
  7.     </context:component-scan>  
  8.   
  9. app-web.xml  
  10.   
  11.  <context:component-scan base-package="com.qunar.b2c">  
  12.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />  
  13.    </context:component-scan>  

 

     在开发定义bean的时候, 也需要注意,把bean定义到哪一层级.

分享到:
评论

相关推荐

    25个经典的Spring面试问答

    如何用基于XML配置的方式配置Spring 如何用基于Java配置的方式配置Spring 怎样用注解的方式配置Spring 请解释Spring Bean的生命周期 Spring Bean的作用域之间有什么区别 什么是Spring inner beans Spring框架中的...

    Spring的学习笔记

    (一) Annotation注解方式配置事务管理 31 (二) Spring事务选项 35 (三) XML文件形式配置Spring事务管理 37 四、 HibernateTemplate 38 (一) HibernateTemplate 38 (二) HibernateDaoSupport 39 第十一课:Spring整合...

    spring2.5 学习笔记

    (一) Annotation注解方式配置事务管理 31 (二) Spring事务选项 35 (三) XML文件形式配置Spring事务管理 37 四、 HibernateTemplate 38 (一) HibernateTemplate 38 (二) HibernateDaoSupport 39 第十一课:Spring整合...

    Spring中文帮助文档

    2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut ...

    Spring API

    2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut ...

    spring基础

    Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分 XML 配置的功能。 @Autowired,按照类型注入 @Resource,默认按照名称注入,如果名称没有指定,则按照类型注入 @Resource 的...

    springmybatis

    MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个...

    spring_MVC源码

    弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,...

    java微信公众号MVC开发框架

    微信接口服务类位于com.github.jweixin.jwx.weixin.service包中,在spring配置文件中通过扫描包载入服务,在web mvc框架和微信控制器类中都可以通过@Autowired注解注入,与其他spring普通的服务类主键使用方式一致,...

Global site tag (gtag.js) - Google Analytics