【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)执行。

【Spring】EnableXXX

   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 {
}

相关推荐