@SpringBootApplication注解分析 :

被@SpringBootApplication注解的类,会被识别为SpringBoot的启动类,它是一个自定义的注解。

@Target({ElementType.TYPE})//规定该注解用于类上
@Retention(RetentionPolicy.RUNTIME)//规定该注解能保留到运行时,这样才能被反射获取注解信息
@Documented
@Inherited//规定了被@SpringBootApplication注解的类的子类也默认被@SpringBootApplication注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
。。。。。。。省略了注解里的元数据定义。。。。。。。。。。
}

源码里前四个注解都是元注解,@ComponentScan是个扫描注解。@SpringBootConfiguration和
@EnableAutoConfiguration才是@SpringBootApplication的关键

总结:@SpringBootApplication是@SpringBootConfiguration和
@EnableAutoConfiguration的复合注解

(1)@SpringBootConfiguration源码分析

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

结论:@SpringBootConfiguration就是一个@Configuration注解

@Configuration源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

@Configuration是一个@Component注解,而@Component仅仅表明这个类是一个组件,是Spring的一个Bean,可以作用于任何层。

总结:@SpringBootConfiguration归根到底就是一个@Component注解,它仅仅表明这个启动类是Spring容器里的一个bean。

(2) @EnableAutoConfiguration源码分析

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

@EnableAutoConfiguration是一个复合注解,由@AutoConfigurationPackage和
@Import({AutoConfigurationImportSelector.class})组成(其余四个是元注解)。其中@Import注解导入了一个AutoConfigurationImportSelector.class类,这是一个自动配置的选择器,这个类是通过反射的机制获取某些类的注解元数据,通过元数据来实现特定的功能。SpringBoot启动后,并不会加载所有的配置,它会通过AutoConfigurationImportSelector.class来选取部分配置加载。
@AutoConfigurationPackage其实也是一个@Import注解,它导入的是Registrar.class,它是AutoConfigurationPackages抽象类的静态内部

总结:@EnableAutoConfiguration注解的作用主要就是导入了两个类对象,分别为AutoConfigurationImportSelector.class和Registrar.class,关键是AutoConfigurationImportSelector.class。


提示:这里描述项目中遇到的问题:

例如:数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据
APP 中接收数据代码:

@Override
	public void run() {
		bytes = mmInStream.read(buffer);
		mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();
	}

启动类里run方法分析

run方法源码

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }

它返回的是一个 ConfigurableApplicationContext类型的对象, ConfigurableApplicationContext是一个接口,同时也是 ApplicationContext的子类。而 ApplicationContext却是我们熟悉的Spring容器,是一个管理所有Bean的容器。

现在我们来通过代码验证一下:

跟往常一样,编写一个简单的SpringBoot项目。

Controller类:

@RestController(value = "test")
public class test {
    @RequestMapping("/test")
    public void test(){
        System.out.println("我被Spring容器调用了!!!");
    }

}

test类是一个中规中矩的接受前端请求的一个接口类。

启动类:

@SpringBootApplication
    public class BootClass {
        public static void main(String[] args){
            ConfigurableApplicationContext applicationContext =  SpringApplication.run(BootClass.class,args);
             test t = (test)applicationContext.getBean("test");
             t.test();
        }
    }

在启动类的主函数中我用applicatContext来获取了run返回的对象,前面我说了run返回的其实就是一个Spring容器,通过Spring容器的getBean方法,我获取了id为test的这个bean,也就是@RestController(value = “test”)注解里的元数据。通过这些操作我就获取了test对象,从而执行了它的方法。

最后执行成功:

SpringBoot如何自定义场景启动器 springboot自定义启动类注解_元数据