ApplicationContextAware接口的拓展和使用

ApplicationContextAware接口只有一个方法:

public interface ApplicationContextAware extends Aware {
    
    
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

此接口的介绍:
不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。

当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean。换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象。

官方介绍的翻译:

接口由希望被其运行的ApplicationContext通知的任何对象实现。

实现这个接口是有意义的,例如,当一个对象需要访问一组协作bean时。请注意,通过bean引用进行配置比仅仅为了bean查找目的实现此接口更可取。

如果一个对象需要访问文件资源,例如,想要调用getResource,想要发布一个应用事件,或者需要访问MessageSource,这个接口也可以实现。然而,最好在这样一个特定的场景中实现更具体的ResourceLoaderAware、ApplicationEventPublisherAware或MessageSourceAware接口。
参数applicationContext—要被该对象使用的applicationContext对象

ApplicationContextAware接口的作用

实现**ApplicationContextAware**接口。重写或继承里面的方法。
主要可以实现的功能:

  1. 根据byType获取byName获取Bean对象;
  2. 根据byName判断Bean对象是否存在;
  3. 根据bean对象的name获取type;
  4. 根据bean对象的type获取names;

需要注意的是,需要将这个类放入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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41358574/article/details/121117694
今日推荐