问题说明
最近看到 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>
Spring.xml
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("事物进行回滚");
- }
- }
TransactionUtil.java
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 ... 」
要细心 遇到异常不要紧 慢慢分析!!!
谢谢你这么忙还来我的看我的博客奥
如果有哪些地方写的不好希望能够指出!
为了变得更强 一起加油吧~
来源: https://www.cnblogs.com/cat-/p/10014477.html