Spring 父类变量注入失败的解决

目录
  • Spring 父类变量注入失败
    • 下面小记下这个过程
  • Spring通过父类注入公用属性的技巧
    • XML配置方式提取父类
    • Annotation方式提取父类

Spring 父类变量注入失败

昨天遇到一个Action里面Service注入失败,换种说法应该说是根本没有发生注入,本来很简单的一个问题,但由于在项目中多个Action进行了继承,才最终导致了这个看似奇怪的问题。

下面小记下这个过程

收到同事问题,“有个Action请求一直调用报控指针,service一直是空的导致的!”

初步看了代码及配置,没有发现什么问题,起初怀疑是Action没有get方法所致,然后加上仍然无效;然后单步做了各种变量名的替换,一直一样问题 ,这过程中一直关注java代码确忽略了页面请求,通过页面请求发现代码真正逻辑是页面请求了一个子类Action的方法,而这个方法里面调用了父类的一个方法,此时父类里面的Service一直无法注入,对于上面所提的这种需求,实际上是需要在子类做Spring注入的同时也进行父类的Spring注入,那么这种需要这样的配置:

<bean id="****Action" class="com.**.**.contrl.**.mgr.action.**Action" scope="prototype" parent="termCommonAction">
  <property name="orderVerifyApiFacade" ref="ord.bizprov.orderVerifyApiFacade"/>
  <property name="orderListQryApiFacade" ref="ord.query.orderListQryApiFacade"/>
  <property name="channelQryApiFacade" ref="cfguse.channel.channelQryApiFacade" />
</bean> 

经过上面的设置以后,请求子类的Action方法,子类方法中调用父类方法时,就不会出现父类不发生注入的问题了。

Spring通过父类注入公用属性的技巧

XML配置方式提取父类

在使用Spring + Hibernate框架,或者SSH2等框架的时候,在开发中只有一个基本的DAO是现在的非常流行的做法。然后,在看过多份这种代码以后,都是在每个业务类中声明了一个DAO属性,并且在Bean配置中,对每个业务类分别注入DAO。具体情形示例如下:

BaseDAO代码:

public class BaseDAO {
 public String service() {
  return "Success!";
 }
}

Services代码:

//第一个业务类
public class ServiceA {
 public String service() {
  return baseDAO.service();
 }
 protected BaseDAO baseDAO;
 public void setBaseDAO(BaseDAO baseDAO) {
  this.baseDAO = baseDAO;
 }
}

//第二个业务类
public class ServiceB {
 public String service() {
  return baseDAO.service();
 }

 protected BaseDAO baseDAO;
 public void setBaseDAO(BaseDAO baseDAO) {
  this.baseDAO = baseDAO;
 }
}

Spring的Bean配置如下:

<bean id="baseDAO" class="com.watson.BaseDAO" />
<bean id="serviceA" class="com.watson.ServiceA">
 <property name="baseDAO" ref="baseDAO" />
</bean>
<bean id="serviceB" class="com.watson.ServiceB">
 <property name="baseDAO" ref="baseDAO" />
</bean>

这样的做法是现在的主流。这样做不是说那里错了,还是那句老话:这样做肯定不优美,谁让人有时候是一根筋呢?

能够想到的办法是用一个父类来包含一些业务层公用的业务逻辑和属性。所以可以将上面的代码和配置。

Services代码改写如下:

//所有业务类的父类
public class BaseService {
 protected BaseDAO baseDAO;
 public void setBaseDAO(BaseDAO baseDAO) {
  this.baseDAO = baseDAO;
 }
}
//第一个业务类
public class ServiceA extends BaseService  {
 public String service() {
  return baseDAO.service();
 }
}
//第二个业务类
public class ServiceB extends BaseService  {
 public String service() {
  return baseDAO.service();
 }
}

Spring的Bean配置改写如下:

<bean id="baseDAO" class="com.watson.BaseDAO" />
<bean id="BaseService" class="com.watson.BaseService" />
 <property name="baseDAO" ref="baseDAO" />
</bean>
<bean id="serviceA" class="com.watson.ServiceA" />
<bean id="serviceB" class="com.watson.ServiceB" />

这样一来是不简洁了很多?尤其在实际项目有太多Bean的时候。然后,这里不会达到我们预想的结果,因为这里会出现如下的错误:

exception:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is

java.lang.NullPointerException

......

root cause:

java.lang.NullPointerException:......

而出错代码就是每个业务中调用baseDAO的那行代码。这说明注入失败了。翻阅Spring的Bean注入详解之后,很快就可以找应该设置子类Bean配置的parent属性。所以这里可以修改设置。

Spring的Bean配置改写如下:

<bean id="baseDAO" class="com.watson.BaseDAO" />
<bean id="BaseService" class="com.watson.BaseService" />
 <property name="baseDAO" ref="baseDAO" />
</bean>
<bean id="serviceA" class="com.watson.ServiceA" parent="baseService" />
<bean id="serviceB" class="com.watson.ServiceB" parent="baseService" />

这个时候再运行,就不会报错了。原理是:在Spring的子类Bean配置中,其parent属性作用是指定其父类,并继承父类的注入属性。不仅如此,子类还可以修改或者覆盖父类的属性值。例如上述代码中的子类修改父类的baseDAO到属性:

<bean id="BaseService" class="com.watson.BaseService" />
 <property name="baseDAO" ref="baseDAO" />
</bean>
<bean id="serviceA" class="com.watson.ServiceA" parent="baseService" />
<property name="baseDAO" ref="baseDAO2" />
</bean>

而对于父类的List等集合属性,子类可以继承父类的值,并且在其基础上进行增加新的值:

<bean id="BaseService" class="com.watson.BaseService" />
 <property name="listValue">
  <list>
   <value>listValue1</value>
   <value>listValue2</value>
  </list>
 </property>
</bean>
<bean id="serviceA" class="com.watson.ServiceA" parent="baseService" />
 <property name="listValue">
  <list>
   <value>listValue3</value>
   <value>listValue4</value>
  </list>
 </property>
</bean>

Annotation方式提取父类

上面的方法是在XML配置文件中进行的配置。而对现在Spring3流行的Annotation方式,其实更加的方便,完整示例如下:

BaseDAO代码:

@Component
public class BaseDAO {
 public String service() {
  return "Success!";
 }
}

Services代码:

//所有业务类的父类
public class BaseService {
 @Autowired
 protected BaseDAO baseDAO;
}

//第一个业务类
@Component
public class ServiceA extends BaseService  {
 public String service() {
  return baseDAO.service();
 }
}
//第二个业务类
@Component
public class ServiceB extends BaseService  {
 public String service() {
  return baseDAO.service();
 }
}

Action层代码:

@Controller
@RequestMapping(value = "/testaction")
public class TestAction {
 @Autowired
 private ServiceA service;

 @RequestMapping(value = "/")
 public @ResponseBody String home(Model model) {
  return service.service();
 }
}

这里根本就不需要进行parent属性子类的配置,可以完美的提取父类,并且可以顺利的使用父类的公用属性。至于原理,没有去看源码的处理方式,估计和上述XML配置是异曲同工的,只是在这里增加了对父类的检测。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈spring DI 依赖注入方式和区别

    目录 spring DI 3种DI注解的区别 1 @Autowired 2 @Inject 3 @Resource 3种注入方式的区别 1 field注入 2 构造器注入 3 setter注入 构造器注入的好处 1 依赖不可变 2 依赖不为空 3 完全初始化状态 4 避免循环依赖 5 总结 spring DI Spring框架对Java开发的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反转)和AOP,平时使用最多的就是其中的IOC,我们通过将组件交由Sp

  • springboot 无法扫描到父类模块中Bean的原因及解决

    目录 springboot 无法扫描到父类模块中Bean 现象: 如何解决 解决方案 spring boot 启动就自动关闭 之 找不到bean 解决方法: 原因: 以下收集别的解释: 所以有两种解决办法: springboot 无法扫描到父类模块中Bean 现象: 我定义了两个模块 A 和 B .B模块依赖A模块 A模块中我定义了一个@Component 却发现在B模块中我无法扫描到这个Bean导入注入失败 如何解决 查阅得知,在springboot中的bean扫描是扫描同级目录或者下级目录,

  • Spring使用@Autowired为抽象父类注入依赖代码实例

    这篇文章主要介绍了Spring使用@Autowired为抽象父类注入依赖代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 有时候为了管理或者避免不一致性,希望具体服务统一继承抽象父类,同时使用@Autowired为抽象父类注入依赖.搜了了网上,有些解决方法实现实在不敢恭维,靠子类去注入依赖,那还有什么意义,如下: 父类: public abstract class BaseCar { Settings settings; } @Compo

  • Spring 父类变量注入失败的解决

    目录 Spring 父类变量注入失败 下面小记下这个过程 Spring通过父类注入公用属性的技巧 XML配置方式提取父类 Annotation方式提取父类 Spring 父类变量注入失败 昨天遇到一个Action里面Service注入失败,换种说法应该说是根本没有发生注入,本来很简单的一个问题,但由于在项目中多个Action进行了继承,才最终导致了这个看似奇怪的问题. 下面小记下这个过程 收到同事问题,"有个Action请求一直调用报控指针,service一直是空的导致的!" 初步看了

  • Spring自动注入失败的解决方法

    Spring自动注入失败如何解决? 我有一个被Spring @Service注解的类(MileageFeeCalculator),它有一个用@Autowired注入的变量(rateService),但是当我用这个变量的时候,它显示为null.日志显示MileageFeeCalculator bean和MileageRateService bean都被创建了,但是当我调用service上的mileageCharge ()方法时,就会报NullPointerException错误.为什么Spring

  • 因Spring AOP导致@Autowired依赖注入失败的解决方法

    发现问题: 之前用springAOP做了个操作日志记录,这次在往其他类上使用的时候,service一直注入失败,找了网上好多内容,发现大家都有类似的情况出现,但是又和自己的情况不太符合.后来总结自己的情况发现:方法为private修饰的,在AOP适配的时候会导致service注入失败,并且同一个service在其他的public方法中就没有这种情况,十分诡异. 解决过程: 结合查阅的资料进行了分析:在org.springframework.aop.support.AopUtils中: publi

  • 详解Spring关于@Resource注入为null解决办法

    初学spring,我在dao层初始化c3p0的时候,使用@Resource注解新建对象是发现注入为null,告诉我 java.lang.NullPointerException. @Repository public class UserDaoImpl implements UserDao { @Resource ComboPooledDataSource dataSource; 反复检查了配置文件,没有发现任何问题,最后在同学的帮助下终于发现了问题的所在,特记录于此,一个教训. 问题就出在我的

  • RocketMQTemplate 注入失败的解决

    RocketMQTemplate 注入失败 在使用rocketmq 发送消息时,会发现 @Autowired private RocketMQTemplate rocketMQTemplate; 注入RocketMQTemplate 失败. 解决方案 究其原因是因为,配置文件中,我们没有添加 上图中蓝色的两行代码,指定发送的组名.写上后,问题解决. 好了,再来说说RocketMQTemplate 的基本使用吧~ RocketMQTemplate的使用 1.pom.xml依赖 <dependenc

  • SpringBoot Test类注入失败的解决

    如下所示 本来 bookService的引用一直是null. 导致每次测试都报空指针异常. 然后现在继承相应的 ApplicationTests类,然后使用@Component将该类注册为组件.就可以正常注入了. 补充:关于springboot test @Mapper ,@Autiwired注入无效的问题 @SpringBootTest() @RunWith(SpringRunner.class) public class ProductMapperTest { @Autowired Prod

  • spring boot静态变量注入配置文件详解

    本文实例为大家分享了spring boot静态变量注入配置文件的具体代码,供大家参考,具体内容如下 spring 静态变量注入 spring 中不支持直接进行静态变量值的注入,我们看一下代码: @Component(value = "KafkaConfig") @ConfigurationProperties(prefix = "baseConfig") public class KafkaConfig { private static String logBrok

  • springboot多模块化整合mybatis,mapper自动注入失败问题及解决

    目录 springboot多模块化整合mybatis,mapper自动注入失败 问题 解决 springboot mapper注入失败的一种原因 具体情况是 解决办法 springboot多模块化整合mybatis,mapper自动注入失败 问题 启动类添加@MapperScan或@ComponentScan,mapper类添加@Mapper或@Repository ==> Consider defining a bean of type 'com.ten.mapper.UserMapper'

  • Spring 静态变量/构造函数注入失败的解决方案

    目录 1.案例1:Spring对静态变量的注入为空 2.案例2:在构造函数中使用Spring容器中的Bean对象,得到的结果为空 补充 1.案例1:Spring对静态变量的注入为空 案例代码如下: @Component public class HelloWorld { /** * 错误案例:这种方式是不能给静态变量注入属性值的 */ @Value("${hello.world}") public static String HELLO_WORLD; } 解决方案一:@Value注解加

  • 解决netty中spring对象注入失败的问题

    目录 netty中spring对象注入失败 发现了问题所在 在netty中注入spring成份 可以通过以下方式 netty中spring对象注入失败 今天在做项目的时候发现在netty中注入service失败,百度许久后也找不到答案(@Component,@PostConstruct)未起作用,后灵光一现 发现了问题所在 如图: 这些地方都必须通过spring注入才能实现其他依赖注入,之前这里都是采用new的,所以导致spring注入失败 在netty中注入spring成份 前不久,在Nett

随机推荐