SpringBoot的入门(三)

简介: SpringBoot的入门(三)

SpringBoot-@Enable*注解的工作原理

这也就是为什么SpringBoot能够做到零配置的原因所在:

@Enable:启用一些特征来帮我们做一些事情。

写一个实例:写一个线程

  1. package com.boot.enable.bootenable;
  2. import org.springframework.stereotype.Component;
  3. import java.util.concurrent.TimeUnit;
  4. @Component
  5. public class RunnableDemo implements  Runnable {
  6.    @Override
  7.    public void run() {
  8.        for(int i=0;i<10;i++){
  9.            System.out.println("-----------"+(i+1));
  10.            try {
  11.                TimeUnit.SECONDS.sleep(1);
  12.            } catch (InterruptedException e) {
  13.                e.printStackTrace();
  14.            }

  15.        }
  16.    }
  17. }

主函数如下:

  1. package com.boot.enable.bootenable;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.context.ConfigurableApplicationContext;
  5. import org.springframework.scheduling.annotation.EnableAsync;

  6. @SpringBootApplication
  7. public class BootEnableApplication {
  8.    public static void main(String[] args) {
  9.        ConfigurableApplicationContext context =
  10.                SpringApplication.run(BootEnableApplication.class, args);
  11.        Runnable contextBean = context.getBean(Runnable.class);
  12.        System.out.println("---------------start----------------");
  13.        contextBean.run();
  14.        System.out.println("---------------close----------------");
  15.        context.close();
  16.    }
  17. }

运行的结果如下:这时执行的效果就是一个同步的,顺序执行的。

然而在springBoot中可以启用异步的方式来让我们的方法去异步的去执行:

1,在方法上加上注解:@Async,如果这个方法被异步的去执行的话:

这个注解:它用的是并发编程的juc下的executor。

和spring的TaskExecutor:异步编程的模型来做的。

  1. package org.springframework.scheduling.annotation;

  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;

  7. @Target({ElementType.METHOD, ElementType.TYPE})
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface Async {
  11.    String value() default "";
  12. }

2,然后在主类上去启用这个异步的特征:告诉她要启用异步的方式去配置

@EnableAsync

  1. package com.boot.enable.bootenable;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.context.ConfigurableApplicationContext;
  5. import org.springframework.scheduling.annotation.EnableAsync;

  6. @SpringBootApplication
  7. @EnableAsync
  8. public class BootEnableApplication {
  9.    public static void main(String[] args) {
  10.        ConfigurableApplicationContext context =
  11.                SpringApplication.run(BootEnableApplication.class, args);
  12.        Runnable contextBean = context.getBean(Runnable.class);
  13.        System.out.println("---------------start----------------");
  14.        contextBean.run();
  15.        System.out.println("---------------close----------------");
  16.        context.close();
  17.    }
  18. }

运行的结果如下:这时就是异步的操作了,主线程执行完了,异步的线程还在执行。

总结:原来没有学习springBoot的时候在写一个异步操作的话必须用到callable和FeauterTasker才能够做到。而学习了springBoot的话两步操作就可以了:1,在方法上标注为异步的方法的注解 .  2,  在主方法上启用异步的注解。

原理如下:

@EnableAsync=@Import({AsyncConfigurationSelector.class})

最主要的作用是这个@Import的注解:

源代码如下:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //

  5. package org.springframework.scheduling.annotation;

  6. import java.lang.annotation.Annotation;
  7. import java.lang.annotation.Documented;
  8. import java.lang.annotation.ElementType;
  9. import java.lang.annotation.Retention;
  10. import java.lang.annotation.RetentionPolicy;
  11. import java.lang.annotation.Target;
  12. import org.springframework.context.annotation.AdviceMode;
  13. import org.springframework.context.annotation.Import;

  14. @Target({ElementType.TYPE})
  15. @Retention(RetentionPolicy.RUNTIME)
  16. @Documented
  17. @Import({AsyncConfigurationSelector.class})
  18. public @interface EnableAsync {
  19.    Class<? extends Annotation> annotation() default Annotation.class;

  20.    boolean proxyTargetClass() default false;

  21.    AdviceMode mode() default AdviceMode.PROXY;

  22.    int order() default 2147483647;
  23. }

AsyncConfigurationSelector这个类继承了AdviceModeImportSelector<EnableAsync>

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //

  5. package org.springframework.scheduling.annotation;

  6. import org.springframework.context.annotation.AdviceMode;
  7. import org.springframework.context.annotation.AdviceModeImportSelector;
  8. import org.springframework.lang.Nullable;

  9. public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
  10.    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

  11.    public AsyncConfigurationSelector() {
  12.    }

  13.    @Nullable
  14.    public String[] selectImports(AdviceMode adviceMode) {
  15.        switch(adviceMode) {
  16.        case PROXY:
  17.            return new String[]{ProxyAsyncConfiguration.class.getName()};
  18.        case ASPECTJ:
  19.            return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
  20.        default:
  21.            return null;
  22.        }
  23.    }
  24. }

然后这个类AdviceModeImportSelector实现了

ImportSelector这个接口,从而去判断是哪种类型,如果是代理的话,就返回代理对象的数组,如果是切面的话,就返回切面的数组的实例到spring容器中。

在这个类里面异步回调的处理器 AsyncAnnotationBeanPostProcessor。在这里就会开启一个线程对象去执行上面的方法。

  1. public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
  2.    public ProxyAsyncConfiguration() {
  3.    }

  4.    @Bean(
  5.        name = {"org.springframework.context.annotation.internalAsyncAnnotationProcessor"}
  6.    )
  7.    @Role(2)
  8.    public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
  9.        Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
  10.        AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
  11.        Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
  12.        if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
  13.            bpp.setAsyncAnnotationType(customAsyncAnnotation);
  14.        }

  15.        if (this.executor != null) {
  16.            bpp.setExecutor(this.executor);
  17.        }

  18.        if (this.exceptionHandler != null) {
  19.            bpp.setExceptionHandler(this.exceptionHandler);
  20.        }

  21.        bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
  22.        bpp.setOrder((Integer)this.enableAsync.getNumber("order"));
  23.        return bpp;
  24.    }
  25. }

总结:@Enable*的特性就是依赖于@Impor这个这个特性。springBoot的入门(四)写到@Import注解的特性。

相关文章
|
13小时前
|
Java 容器 Spring
SpringBoot入门(六)
SpringBoot入门(六)
|
13小时前
|
消息中间件 NoSQL Java
SpringBoot的入门(五)
SpringBoot的入门(五)
|
13小时前
|
监控 Java Spring
SpringBoot的入门(四)
SpringBoot的入门(四)
|
13小时前
|
Java API 容器
SpringBoot入门(十)
SpringBoot入门(十)
|
13小时前
|
JSON Java API
SpringBoot入门(八)
SpringBoot入门(八)
|
13小时前
|
NoSQL Java Redis
SpringBoot的入门(一)
SpringBoot的入门(一)
|
13小时前
|
JSON Java 数据格式
SpringBoot入门(七)
SpringBoot入门(七)
|
13小时前
|
Java 应用服务中间件 nginx
SpringBoot入门(九)
SpringBoot入门(九)
|
3月前
|
Java 数据库连接 Maven
|
3月前
|
Java Maven Spring
2.springboot入门
2.springboot入门
23 0