• 【Spring】EnableXXX


    @EnableXXX这一类注解的作用:就是用来启用某一个功能的配置。启用某一功能,仅需要加上一个注解即可生效,可以使组建之间的相互依赖降低了耦合性。

      • @EnableWebSecurity
      • @EnableScheduling
      • @EnableAsync
      • @EnableWebMvc
      • @EnableCaching
      • @EnableAutoConfiguration

      通常代码使用逻辑:以@EnableCaching为例,如果没有配置@EnableCaching,那么@Cacheable注解就不会生效。原因是:@EnableXXX通过相关逻辑,判断某个字段/方法/类上面是否存在相关的注解,如果存在,则让其生效。 


     @EnableScheduling实现逻辑

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Import({SchedulingConfiguration.class})
    @Documented
    public @interface EnableScheduling {
    }

    2.1 关键实现1:SchedulingConfiguration类定义

    @Configuration(
        proxyBeanMethods = false
    )
    @Role(2)
    public class SchedulingConfiguration {
        public SchedulingConfiguration() {
        }
    
        @Bean(
            name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
        )
        @Role(2)
        public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
            return new ScheduledAnnotationBeanPostProcessor();
        }
    }
    View Code

     ScheduledAnnotationBeanPostProcessor.java,实现了多个接口

    public class ScheduledAnnotationBeanPostProcessor implements ScheduledTaskHolder, MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware, SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
        public static final String DEFAULT_TASK_SCHEDULER_BEAN_NAME = "taskScheduler";
        protected final Log logger = LogFactory.getLog(this.getClass());
        private final ScheduledTaskRegistrar registrar;
        @Nullable
        private Object scheduler;
        @Nullable
        private StringValueResolver embeddedValueResolver;
        @Nullable
        private String beanName;
        @Nullable
        private BeanFactory beanFactory;
        @Nullable
        private ApplicationContext applicationContext;
        private final Set<Class<?>> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap(64));
        private final Map<Object, Set<ScheduledTask>> scheduledTasks = new IdentityHashMap(16);

      1、实现了继承自:BeanPostProcessor::ProcessAfterInitialization(Object bean, String beanName) 实现,判断方法上面是否存在@Scheduled注解

    public Object postProcessAfterInitialization(Object bean, String beanName) {
            if (!(bean instanceof AopInfrastructureBean) && !(bean instanceof TaskScheduler) && !(bean instanceof ScheduledExecutorService)) {
                Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
                if (!this.nonAnnotatedClasses.contains(targetClass) && AnnotationUtils.isCandidateClass(targetClass, Arrays.asList(Scheduled.class, Schedules.class))) {
                    Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (method) -> {
                        Set<Scheduled> scheduledAnnotations = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);
                        return !scheduledAnnotations.isEmpty() ? scheduledAnnotations : null;
                    });
                    if (annotatedMethods.isEmpty()) {
                        this.nonAnnotatedClasses.add(targetClass);
                        if (this.logger.isTraceEnabled()) {
                            this.logger.trace("No @Scheduled annotations found on bean class: " + targetClass);
                        }
                    } else {
                        annotatedMethods.forEach((method, scheduledAnnotations) -> {
                            scheduledAnnotations.forEach((scheduled) -> {
                                this.processScheduled(scheduled, method, bean);
                            });
                        });
                        if (this.logger.isTraceEnabled()) {
                            this.logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName + "': " + annotatedMethods);
                        }
                    }
                }
    
                return bean;
            } else {
                return bean;
            }
        }
    View Code

      如果存在@Scheduled注解,则在后续处理中,继续解析@Scheduled注解中各种关于定时周期的定义,如fixRate(下图),放入定时任务(最终封装成 java.util.concurrent.ScheduledFuture)执行。

       2、实现了继承自DisposableBean::destroy()方法,最终调用线程池线程(ScheduledFuture::cacel) 和线程池的关闭(ScheduledExecutorService::shutdownNow

    public void destroy() {
            synchronized(this.scheduledTasks) {
                Collection<Set<ScheduledTask>> allTasks = this.scheduledTasks.values();
                Iterator var3 = allTasks.iterator();
    
                label25:
                while(true) {
                    if (var3.hasNext()) {
                        Set<ScheduledTask> tasks = (Set)var3.next();
                        Iterator var5 = tasks.iterator();
    
                        while(true) {
                            if (!var5.hasNext()) {
                                continue label25;
                            }
    
                            ScheduledTask task = (ScheduledTask)var5.next();
                            task.cancel();
                        }
                    }
    
                    this.scheduledTasks.clear();
                    break;
                }
            }
    
            this.registrar.destroy();
        }
    View Code

    2.2 关键实现2:@Import注解定义

      实现的功能:加载它自己对应的配置类,然后启动他的功能。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
        Class<?>[] value();
    }

      @Import 注解导入的类 有三种,分别是:

        1、ImportSelector: 比如@EnableAsync

    @Import({AsyncConfigurationSelector.class})
    public @interface EnableAsync {

        2、ImportBeanDefinitionRegistrar

        3、普通类:会当作为配置类去处理。

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @Documented
    @Import({DelegatingWebMvcConfiguration.class})
    public @interface EnableWebMvc {
    }
  • 相关阅读:
    使用插件和不使用插件实现select的框
    利用sshtunnel实现跳板机的效果[嵌套ssh实现]
    laravel中get()与 first()区别、collection与stdClass的区别
    Laravel 安全:避免 SQL 注入
    MAC 终端走代理服务器
    Python--Virtualenv简明教程(转载https://www.jianshu.com/p/08c657bd34f1)
    Charles 如何抓取https数据包
    爬虫出现Forbidden by robots.txt(转载 https://blog.csdn.net/zzk1995/article/details/51628205)
    Scrapy框架的学习(6.item介绍以及items的使用(提前定义好字段名))转载https://blog.csdn.net/wei18791957243/article/details/86259688
    python xpath
  • 原文地址:https://www.cnblogs.com/clarino/p/15173185.html
Copyright © 2020-2023  润新知