zoukankan      html  css  js  c++  java
  • @Autowired注入为null问题分析

    题说明

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

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

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

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

    工程结构

    代码片段

    spring.xml

    复制代码
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="
     6         http://www.springframework.org/schema/beans
     7         http://www.springframework.org/schema/beans/spring-beans.xsd
     8         http://www.springframework.org/schema/context
     9         http://www.springframework.org/schema/context/spring-context.xsd">
    10 
    11     <!-- Spring注解扫描 -->
    12     <context:component-scan base-package="com.*" />
    13 
    14     <!-- 1. 数据源对象: C3P0连接池 -->
    15     <bean id="dataSource"
    16         class="com.mchange.v2.c3p0.ComboPooledDataSource">
    17         <property name="driverClass" value="org.h2.Driver"></property>
    18         <property name="jdbcUrl"
    19             value="jdbc:h2:tcp://192.168.190.1/~/test"></property>
    20         <property name="user" value="sa"></property>
    21         <property name="password" value="123"></property>
    22     </bean>
    23 
    24     <!-- 2. JdbcTemplate工具类实例 -->
    25     <bean id="jdbcTemplate"
    26         class="org.springframework.jdbc.core.JdbcTemplate">
    27         <property name="dataSource" ref="dataSource"></property>
    28     </bean>
    29 
    30     <!-- 3.配置事务 -->
    31     <bean id="dataSourceTransactionManager"
    32         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    33         <property name="dataSource" ref="dataSource"></property>
    34     </bean>
    35 
    36 </beans>
    复制代码

     Test.java

    复制代码
    1 public class Test {
    2     public static void main(String[] args) {
    3         ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
    4                 "spring.xml");
    5         ServiceIF service = (ServiceIF) classPathXmlApplicationContext.getBean("serviceImpl");
    6         service.add("小王", 23);
    7     }
    8 }
    复制代码

    TransactionUtil.java

    复制代码
     1 @Component("transactionUtil")
     2 public class TransactionUtil {
     3 
     4     /**
     5      * 初始化数据源
     6      */
     7     @Autowired
     8     private DataSourceTransactionManager dataSourceTransactionManager;
     9 
    10     /**
    11      * 开启事务
    12      * 
    13      * @return
    14      */
    15     public TransactionStatus begin() {
    16         TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
    17         System.out.println(" 开启事务成功 ");
    18         return transaction;
    19     }
    20 
    21     /**
    22      * 提交事物
    23      * 
    24      * @param transaction
    25      */
    26     public void commit(TransactionStatus transaction) {
    27         dataSourceTransactionManager.commit(transaction);
    28         System.out.println(" 事物提交成功 ");
    29     }
    30 
    31     /**
    32      * 回滚事务
    33      * 
    34      * @param transaction
    35      */
    36     public void rollback(TransactionStatus transaction) {
    37         dataSourceTransactionManager.rollback(transaction);
    38         System.err.println(" 事物进行回滚 ");
    39     }
    40 }
    复制代码

    ServiceImpl.java

    复制代码
     1 @Service("serviceImpl")
     2 public class ServiceImpl implements ServiceIF {
     3 
     4     @Autowired
     5     TransactionUtil transactionUtil;
     6 
     7     private TransactionStatus transactionStatus = null;
     8 
     9     @Override
    10     public void add(String name, Integer age) {
    11         transactionStatus = transactionUtil.begin();
    12         try {
    13             new DaoImpl().add(name, age);
    14             transactionUtil.commit(transactionStatus);
    15         } catch (Exception e) {
    16             System.err.println("ERROR >>> 执行出现异常 即将进行回滚操作");
    17             transactionUtil.rollback(transactionStatus);
    18         }
    19     }
    20 }
    复制代码

    DaoImpl.java

    复制代码
     1 public class DaoImpl implements DaoIF{
     2 
     3     /**
     4      * 注入jdbc模板类
     5      */
     6     @Autowired
     7     private JdbcTemplate jdbcTemplate;
     8 
     9     /**
    10      * 第一条插入语句
    11      */
    12     private final String SQL_INSERT_01 = "insert into user values (?,?)";
    13 
    14     /**
    15      * 添加sql执行
    16      * 
    17      * @param name
    18      * @param age
    19      */
    20     public void add(String name, Integer age) {
    21         jdbcTemplate.update(SQL_INSERT_01, name, age);
    22     }
    23 }
    复制代码

    运行结果

     问题分析


    解决思路

    我在想 为什么会没有注入进来呢 我明明加了@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 … 」

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

    https://www.cnblogs.com/cat-/p/10014477.html

  • 相关阅读:
    python工具——geoplotlib
    python工具——playwright
    python工具——folium
    python工具——basemap使用二绘制中国地图
    python工具——basemap使用一基本使用
    python工具——Py-Spy
    Ubuntu 安装python3及多版本切换
    PDI(Kettle)的使用七 定时调度
    go 结构体
    Django部属到Windows IIS所遇到的问题及解决方法
  • 原文地址:https://www.cnblogs.com/sjqq/p/10137208.html
Copyright © 2011-2022 走看看