ApplicationContextAware接口只有一个方法:
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
此接口的介绍:
不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。
当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean。换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象。
官方介绍的翻译:
实现**ApplicationContextAware
**接口。重写或继承里面的方法。
主要可以实现的功能:
需要注意的是,需要将这个类放入Spring容器中管理。即使用**@Component
**注解。
需要注意的是:name不是Bean对象的全限定名,而是Spring容器中的Bean名。
实现setApplicationContext此方法的类:
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
//DisposableBean :由希望在销毁时释放资源的bean实现的接口。
// BeanFactory将在对作用域bean的单独销毁时调用destroy方法。
// applicationcontext应该在关闭时释放它的所有单例对象,这是由应用生命周期驱动的。
//出于同样的目的,spring管理的bean也可以实现Java的AutoCloseable接口。
// 实现接口的另一种方法是指定自定义destroy方法,例如在XML bean定义中。
private static ApplicationContext applicationContext = null;
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
}
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
private static void clearHolder() {
log.debug("清除SpringContextHolder中的ApplicationContext:"
+ applicationContext);
applicationContext = null;
}
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
}
SpringContextHolder.applicationContext = applicationContext;
}
}
使用这个上面类在线程对象中得到目标对象的方法,利用反射进行调用:
public class QuartzRunnable implements Callable {
//在Execution类中使用QuartRunnable QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
// quartzJob.getParams());
// Future<?> future = EXECUTOR.submit(task);
private Object target;
private Method method;
private String params;
QuartzRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException {
this.target = SpringContextHolder.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public Object call() throws Exception {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
return null;
}
}
method.invoke(target, params):
对目标object执行方法method,参数为params
调用反射的方法:
@Async
public class ExecutionJob extends QuartzJobBean {
//在QuartManage类中 JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class).
// withIdentity(JOB_NAME + quartzJob.getId()).build();
//执行定时任务
// scheduler.scheduleJob(jobDetail, cronTrigger);
/** 该处仅供参考 */
private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
@Override
@SuppressWarnings("unchecked")
protected void executeInternal(JobExecutionContext context) {
//(1)当Scheduler调用一个Job,就会将JobExecutionContext传递给job的execute方法
// quartz无法调用job的有参构造函数,所以创建job的实例的时候是运用反射机制,通过newInstance创建实例,
// 并且通过JobDetail描述的name与group属性然后给Job设置一些属性。
//
//(2)Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
// 获取spring bean
QuartzLogService quartzLogService = SpringContextHolder.getBean(QuartzLogService.class);
QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class);
QuartzLog log = new QuartzLog();
long startTime = System.currentTimeMillis();
try {
// 执行任务
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
quartzJob.getParams());//这句话中执行了该线程
Future<?> future = EXECUTOR.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
} catch (Exception e) {
logger.error("任务执行失败,任务名称:{}" + quartzJob.getJobName(), e);
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
log.setExceptionDetail(ThrowableUtil.getStackTrace(e));
quartzJob.setIsPause(false);
//更新状态
quartzJobService.updateIsPause(quartzJob);
} finally {
quartzLogService.save(log);
}
}
}