SpringBoot simplifies many configurations, and perhaps even some features no configuration, as long as a default attribute annotations can be achieved, such as previously described the @ EnableTransactionManagement associated with the transaction, there are many such annotations in SpringBoot, although the function is not the same, But they all work the same way. Two typical annotations will be analyzed below.

@EnableScheduling

Scheduled tasks can be easily implemented using @scheduled in conjunction with @enablesCheduling if your business needs Scheduled tasks.

The Class SchedulingConfiguration is imported and entered.

Import the ScheduledAnnotationBeanPostProcessor this class, so to enter.

Timing task method analysis

ScheduledAnnotationBeanPostProcessor is a rear processor, a focus on postProcessAfterInitialization method.

The first half of the method is to find a method with @scheduled and @schedules annotations, and the second half of the process is as follows:

  1. Encapsulate the scheduled task method asScheduledMethodRunnableObject whose run method uses reflection to perform a timed task method
  2. Analyze the annotation Scheduled property to see which one of cron, fixedDelay and fixedRate it is encapsulated into the object and finally represented in the Registrar member variable. FixedDelay indicates the interval since the last execution ends, and fixedRate indicates the interval since the last execution starts.

Take the cron attribute as an example, as shown in the figure, where expression is an expression, trigger analyzes the expression and lists the execution time, and runnable is the thread that executes the scheduled task method.

Creating a thread pool

After all bean instances are complete, the ContextRefreshedEvent event is published. The post-processor listens and eventually enters the finishRegistration method.

ScheduledAnnotationBeanPostProcessor->finishRegistration(): To find the class in the IoC container that implements the SchedulingConfigurer interface, call configureTasks to set the thread pool...... If (this. The registrar. HasTasks () && enclosing the registrar. GetScheduler () = = null) {try {/ / find the IoC container TaskScheduler interface in the bean this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false)); {} the catch (NoUniqueBeanDefinitionException ex) try {/ / there are multiple, Find the IoC container TaskScheduler interface and in the name of TaskScheduler bean enclosing the registrar. SetTaskScheduler (resolveSchedulerBean (enclosing the beanFactory, TaskScheduler.class, true)); } catch (NoSuchBeanDefinitionException ex2) { } } catch (NoSuchBeanDefinitionException ex) { try { // If there is no bean that implements the TaskScheduler interface, Find the IoC container of ScheduledExecutorService interface in the bean enclosing the registrar. SetScheduler (resolveSchedulerBean (enclosing the beanFactory, ScheduledExecutorService.class, false)); {} the catch (NoUniqueBeanDefinitionException ex2) try {/ / there are multiple, Find the bean in the IoC container that implements the ScheduledExecutorService interface and is named taskScheduler this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, true)); } catch (NoSuchBeanDefinitionException ex3) { } } catch (NoSuchBeanDefinitionException ex2) { } } } this.registrar.afterPropertiesSet();Copy the code

Implement SchedulingConfigurer, TaskScheduler, ScheduledExecutorService and inject the IoC container, any of which can customize the thread pool properties. If no configuration is done, An instance of the ThreadPoolTaskScheduler object is returned.

As shown in figure, object instance defined in TaskSchedulingAutoConfiguration ConditionalOnMissingBean tell if we made any configuration, wouldn’t return ThreadPoolTaskScheduler object instances. Note that the thread pool name and number of cores are determined by TaskSchedulingProperties, In the configuration file defines spring. Task. The scheduling. ThreadNamePrefix and spring.. Task scheduling. The pool. The size can, it is not configured by default core number is 1, the thread of the format for the scheduling – XXX.

Perform a task

ScheduledTaskRegistrar->scheduleTasks(): // Even if there is no previous setting, If (this.taskScheduler == null) {this.localExecutor = Executors.newSingleThreadScheduledExecutor(); this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor); }... if (this.cronTasks ! = null) { for (CronTask task : this.cronTasks) { addScheduledTask(scheduleCronTask(task)); }}... ScheduledTaskRegistrar->scheduleCronTask(): scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger()); ScheduledExecutorService Executor = getScheduledExecutor(); return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule(); ReschedulingRunnable is a thread class ReschedulingRunnable->schedule(): / / calculated to perform the task of timing time enclosing scheduledExecutionTime = this. The trigger. NextExecutionTime (enclosing triggerContext); / / how much difference between the current time is long initialDelay = this. ScheduledExecutionTime. GetTime () - System. CurrentTimeMillis (); InitialDelay ms initialDelay ms CurrentFuture = this.executor.schedule(this, initialDelay, timeunit.milliseconds);Copy the code

The internal implementation of cron is good execution time and the difference between the current time, nature or JDK ScheduledThreadPoolExecutor. In the schedule() method, this is a ReschedulingRunnable object, so look at its run() method.

ReschedulingRunnable->run(): // actualExecutionTime = new Date(); // Execute the scheduled task super.run(); Date completionTime = new Date(); // Record the time...... schedule();Copy the code

Schedule () is called again after the task is completed, and schedule() executes the run() method again to achieve the loop effect.

@MapperScan

@mapperscan allows the interface under the attribute path to be automatically injected into the IoC container, often used to inject Mapper.

You import the MapperScannerRegistrar class and enter

Observe it implements ImportBeanDefinitionRegistrar interface, then find it registerBeanDefinitions method, it injected MapperScannerConfigurer the bean into the IoC container, This bean implements BeanDefinitionRegistryPostProcessor interface, then find it postProcessBeanDefinitionRegistry method, The last line scanner. The scan (StringUtils. TokenizeToStringArray (enclosing basePackage, ConfigurableApplicationContext CONFIG_LOCATION_DELIMITERS), here is the scanning the file path, return to the interface class, Set BeanDefinition type to GenericBeanDefinition, beanClass to MapperFactoryBean, autowireMode to 2 AUTOWIRE_BY_TYPE, Finally, add the interface class to the BDM.

conclusion

Feature annotations are best described in the startup class declaration, which makes them easy to view and manage.

  1. Inside annotations
  2. View annotation introduction classes
  3. Analysis of imported classes