@Autowired注入为null问题原因分析

问题说明

最近看到Spring事务,在学习过程中遇到一个很苦恼问题

搭建好Spring的启动环境后出现了一点小问题

在启动时候却出现[java.lang.NullPointerException]

不过因为当时一个小小的疏忽很low的问题 请往下看...

工程结构

代码片段

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- Spring注解扫描 -->
  <context:component-scan base-package="com.*" />

  <!-- 1. 数据源对象: C3P0连接池 -->
  <bean id="dataSource"
    class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="org.h2.Driver"></property>
    <property name="jdbcUrl"
      value="jdbc:h2:tcp://192.168.190.1/~/test"></property>
    <property name="user" value="sa"></property>
    <property name="password" value="123"></property>
  </bean>

  <!-- 2. JdbcTemplate工具类实例 -->
  <bean id="jdbcTemplate"
    class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
  </bean>

  <!-- 3.配置事务 -->
  <bean id="dataSourceTransactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
  </bean>

</beans>

Test.java

public class Test {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
        "spring.xml");
    ServiceIF service = (ServiceIF) classPathXmlApplicationContext.getBean("serviceImpl");
    service.add("小王", 23);
  }
}

TransactionUtil.java

@Component("transactionUtil")
public class TransactionUtil {

  /**
   * 初始化数据源
   */
  @Autowired
  private DataSourceTransactionManager dataSourceTransactionManager;

  /**
   * 开启事务
   *
   * @return
   */
  public TransactionStatus begin() {
    TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
    System.out.println(" 开启事务成功 ");
    return transaction;
  }

  /**
   * 提交事物
   *
   * @param transaction
   */
  public void commit(TransactionStatus transaction) {
    dataSourceTransactionManager.commit(transaction);
    System.out.println(" 事物提交成功 ");
  }

  /**
   * 回滚事务
   *
   * @param transaction
   */
  public void rollback(TransactionStatus transaction) {
    dataSourceTransactionManager.rollback(transaction);
    System.err.println(" 事物进行回滚 ");
  }
}

ServiceImpl.java

@Service("serviceImpl")
public class ServiceImpl implements ServiceIF {

  @Autowired
  TransactionUtil transactionUtil;

  private TransactionStatus transactionStatus = null;

  @Override
  public void add(String name, Integer age) {
    transactionStatus = transactionUtil.begin();
    try {
      new DaoImpl().add(name, age);
      transactionUtil.commit(transactionStatus);
    } catch (Exception e) {
      System.err.println("ERROR >>> 执行出现异常 即将进行回滚操作");
      transactionUtil.rollback(transactionStatus);
    }
  }
}

DaoImpl.java

public class DaoImpl implements DaoIF{

  /**
   * 注入jdbc模板类
   */
  @Autowired
  private JdbcTemplate jdbcTemplate;

  /**
   * 第一条插入语句
   */
  private final String SQL_INSERT_01 = "insert into user values (?,?)";

  /**
   * 添加sql执行
   *
   * @param name
   * @param age
   */
  public void add(String name, Integer age) {
    jdbcTemplate.update(SQL_INSERT_01, name, age);
  }
}

运行结果

问题分析

解决思路

我在想 为什么会没有注入进来呢 我明明加了@Autowired注解

后来猜到可能是Spring.xml配置的问题

看完也没有问题

我就从Java Source一步一步看 发现....

我靠 我就猜测是不是如果用「new Object()」的方式创建实例后 其class中的Bean的注解会失效呢?

然后我尝试在ServiceImpl.java中以注解的方式把DaoIF的实例注入到ServiceImpl,

并在DaoImpl.java的类上面添加@Repository,

把ServiceImpl.java中new DaoImpl()替换成注入的daoImpl。

改修代码

ServiceImpl.java修改后

DaoImpl.java修改后

改修后调试

其实我懂得也不太多 Spring注入的流程那

首先他会把项目中target -> classes 目录下的「.class」文件进行解析

通过Spring.xml中的「context:component-scan」进行注解扫描

如果这个路径下的「.class」文件的类上面是否存在@Component声明的注解

如果被此类注解修饰,Spring会把所有被注解修饰的bean进行实例化操作 供给@Autowired进行注入

(在spring注解的源码中@Service和@Repository等等都继承了@Component注解)

结论

在使用Spring的Bean容器时 千万要确保

配置的注解扫描路径正确

Jar的依赖是否存在

是否在bean的上面加「@Service @Repository @Component … 」

要细心 遇到异常不要紧 慢慢分析!!!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 解决Springboot @Autowired 无法注入问题

    特别提醒:一定要注意文件结构 WebappApplication 一定要在包的最外层,否则Spring无法对所有的类进行托管,会造成@Autowired 无法注入. 1. 添加工具类获取在 Spring 中托管的 Bean (1)工具类 package com.common; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionE

  • 解决SpringBoot项目使用多线程处理任务时无法通过@Autowired注入bean问题

    最近在做一个"温湿度控制"的项目,项目要求通过用户设定的温湿度数值和实时采集到的数值进行比对分析,因为数据的对比与分析是一个通过前端页面控制的定时任务,经理要求在用户开启定时任务时,单独开启一个线程进行数据的对比分析,并将采集到的温湿度数值存入数据库中的历史数据表,按照我们正常的逻辑应该是用户在请求开启定时任务时,前端页面通过调用后端接口,创建一个新的线程来执行定时任务,然后在线程类中使用 @Autowired 注解注入保存历史数据的service层,在线程类中调用service层保存

  • 详解Spring @Autowired 注入小技巧

    今天和同事讨论到Spring自动注入时,发现有这么一段代码特别地困惑,当然大致的原理还是可以理解的,只不过以前从来没有这么用过.想到未来可能会用到,或者未来看别人写的代码时不至于花时间解决同样的困惑,所以小编还是觉得有必要研究记录一下. 一.同一类型注入多次为同一实例 首先让我们先看下这段代码是什么? @Autowired private XiaoMing xiaoming; @Autowired private XiaoMing wanger; XiaoMing.java package co

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

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

  • @Autowired注入为null问题原因分析

    问题说明 最近看到Spring事务,在学习过程中遇到一个很苦恼问题 搭建好Spring的启动环境后出现了一点小问题 在启动时候却出现[java.lang.NullPointerException] 不过因为当时一个小小的疏忽很low的问题 请往下看... 工程结构 代码片段 spring.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springfr

  • 基于spring注入为null的原因及解决方案

    目录 spring注入为null 场景 经检查找出原因 解决方法 @PostConstruct: Spring注入的属性为null可能的情况 保证Bean能够交付给Spring容器 检查实例化的方式 检查注入的位置 spring注入为null 解决方法用到@PostConstruct注解,平常没接触过,写博客记录一下. 场景 在使用Aviator时需要自定义函数,但是在使用自定函数的时候发现@Resource注入的类是null,使用的框架是springboot所以没什么好配置的,在网上找了下原因

  • mysql 字段定义不要用null的原因分析

    一 NULL 为什么这么经常用 (1) java的null null是一个让人头疼的问题,比如java中的NullPointerException.为了避免猝不及防的空指针,需要小心翼翼地各种if判断,麻烦又臃肿. 为此有很多的开源包都有诸多处理 common lang3的StringUtils.isBlank(); CollectionUtils.isEmpty(); guava的Optional 甚至java8也引入了Optional来避免这一问题(和guava的大同小异,用法稍有一点点变化

  • Java @Autowired报错原因分析和4种解决方案

    目录 报错原因分析 解决方案1:关闭报警机制 解决方案2:添加Spring注解 解决方案3:允许注入对象为NULL 解决方案4:使用@Resource注解 总结 前言: 上图的报错信息相信大部分程序员都遇到过,奇怪的是虽然代码报错,但丝毫不影响程序的正常执行,也就是虽然编译器 IDEA 报错,但程序却能正常的执行,那这其中的原因又是为何? 报错原因分析 报错的原因首先是因为 IDEA 强大的报警机制,@Autowired 为 Spring 的注解,含义是将某类动态的注入到当前类中, 如下图所示:

  • JAVA解决在@autowired,@Resource注入为null的情况

    使用SpringMVC或者SSH过程中,有时可能会遇到这么一个问题.就是在一个普通的JAVA类(不是controller也不是action类)中无法注入在spring配置文件中配置的bean. 比如你在一个普通java类想调用某个在spring中配置的service,你会发现不管你用@Resource还是@Autowired注解都无法注入,对象始终是null. 那是因为一般普通的Java类没有被spring代理,自然无法通过spring注入相关的对象.难道这样就不能调用了吗?这里提供下面一个类来

  • 关于@Autowired注入依赖失败的问题及解决

    目录 @Autowired注入依赖失败的问题 1.现象描述 2.问题分析 3.解决方案 @Autowired依赖注入为啥不推荐了 警告内容 依赖注入的方式 @Autowired是干啥的 @Inject是干啥的 @Resource是干啥的 spring建议 @Autowired注入依赖失败的问题 1.现象描述 在Spring Boot项目中使用@Autowired注解,程序启动时发现服务启动失败,提示: Description: Field metrics in com.be.fallback.s

  • 使用@Autowired 注入RedisTemplate报错的问题及解决

    目录 @Autowired 注入RedisTemplate报错 下面是Redis配置类 解决方法一 解决方法二 下面咱们来看一下原因 @Autowired 注入RedisTemplate为null 解决 @Autowired 注入RedisTemplate报错 先看报错信息 Field redisTemplate in xxx.xxx required a bean of type 'org.springframework.data.redis.core. RedisTemplate' that

  • spring 整合mybatis后用不上session缓存的原因分析

    因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验下(spring整合mybatis略,网上一堆),先看看mybatis级别的session的缓存 放出打印sql语句 configuration.xml 加入 <settings> <!-- 打印查询语句 --> <setting name="logImpl"

  • 解决springboot遇到autowire注入为null的问题

    这个问题困扰了很久,有些类不是controller在使用autowired注入的类显示为空,找到网上的方法是在类初始化时主动注入被Autowired的类,如下图 这样的方法是可行的,最后引用时使用上图中doubleTeachSendMsg.doubleTeachService.sendMsg();方法即可,但是使用起来未免太麻烦,而且也不是spring依赖注入的原则,这个出现原因其实就是此类是在bean加载之前被调用,或者springboot在加载时没有识别到此类,所以注入为空,要想使此类被识别

随机推荐