下面我会举例来说明我是如何进行断点追踪的,以spring-boot-2.0.3之quartz集成,不是你想的那样哦!和 spring-boot-2.0.3之quartz集成,数据源问题,源码探究 为背景来讲,需要搞清楚两个点:springboot是如何向quartz注入数据源的,quartz是如何操作数据库的
springboot向quartz注入数据源
QuartzAutoConfiguration是springboot自动配置quartz的入口
将quartz的配置属性设置给SchedulerFactoryBean;将数据源设置给SchedulerFactoryBean:如果有@QuartzDataSource修饰的数据源,则将@QuartzDataSource修饰的数据源设置给SchedulerFactoryBean,否则将应用的数据源(druid数据源)设置给SchedulerFactoryBean,显然我们的应用中没有@QuartzDataSource修饰的数据源,那么SchedulerFactoryBean中的数据源就是应用的数据源;将事务管理器设置给SchedulerFactoryBean。SchedulerFactoryBean,负责创建和配置quartz Scheduler,并将其注册到spring容器中。SchedulerFactoryBean实现InitializingBean的afterPropertiesSet方法,里面有可以设置数据源的过程
可以看到通过org.quartz.jobStore.dataSource设置的dsName(值为quartzDs)最后会被替换成springTxDataSource.加scheduler实例名(我们的应用中是:springTxDataSource.quartzScheduler)。springboot会注册两个ConnectionProvider给quartz:一个dsName叫springTxDataSource.quartzScheduler,有事务;一个dsName叫springNonTxDataSource.quartzScheduler,没事务。
quartz如何操作数据库
我们通过停止定时任务来跟下quartz对数据库的操作
发现quartz用如下方式获取connection
- conn = DBConnectionManager.getInstance().getConnection(getDataSource());
那么我们的job中就可以按如下方式操作数据库了
- package com.lee.quartz.job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.utils.DBConnectionManager;
- import org.springframework.scheduling.quartz.LocalDataSourceJobStore;
- import org.springframework.scheduling.quartz.QuartzJobBean;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.SQLException;
- public class FetchDataJob extends QuartzJobBean {
- // private String dataSourceName = "quartzDs"; // 用此会找不到
- // private String dataSourceName = "springNonTxDataSource.quartzScheduler"; // 不支持事务
- // private String dataSourceName = "springTxDataSource.quartzScheduler"; // 支持事务
- private final String insertSql = "INSERT INTO tbl_sys_user(name, age) VALUES(?,?) ";
- private String schedulerInstanceName = "quartzScheduler"; // 可通过jobDataMap注入进来
- @Override
- protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
- String dsName = LocalDataSourceJobStore.NON_TX_DATA_SOURCE_PREFIX
- + schedulerInstanceName; // 不支持事务
- //String dsName = LocalDataSourceJobStore.TX_DATA_SOURCE_PREFIX + schedulerInstanceName; // 支持事务
- try {
- Connection connection = DBConnectionManager.getInstance().getConnection(dsName);
- PreparedStatement ps = connection.prepareStatement(insertSql);
- ps.setString(1, "张三");
- ps.setInt(2, 25);
- ps.executeUpdate();
- ps.close();
- connection.close(); // 将连接归还给连接池
- System.out.println("插入成功");
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- public void setSchedulerInstanceName(String schedulerInstanceName) {
- this.schedulerInstanceName = schedulerInstanceName;
- }
- }
明确我们的目的,找到合适的切入点,进入断点调试追踪也就容易了。
任我说的天花乱坠,你仍无动于衷,那也只是我一厢情愿,只有局中人才能体会到其中的奥妙!
总结与感悟
(编辑:ASP站长网)
|