天天看点

SpringApplication解读(一):注解

main方法入口:

@SpringBootApplication
public class TestApplication {
	public static void main(String[] args) {
		SpringApplication.run(TestApplication.class, args);
	}
}
           

点击@SpringBootApplication注解,进去后发现:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
   ......
}
           

@Retention @Target @Document @Inherited 四个为元注解:

@Retention:定义注解的保留策略。

                       RetentionPolicy.RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到

                       RetentionPolicy.CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得

                       RetentionPolicy.SOURCE:注解仅存在于源码中,在class字节码文件中不包含

@Target :定义注解的作用目标

                   ElementType.TYPE   //接口、类、枚举、注解

                   ElementType.FIELD //字段、枚举的常量

                   ElementType.METHOD) //方法

                   ElementType.PARAMETER) //方法参数

                   ElementType.CONSTRUCTOR)  //构造函数

                   ElementType.LOCAL_VARIABLE)//局部变量

                   ElementType.ANNOTATION_TYPE)//注解

                   ElementType.PACKAGE) ///包 

@Document :说明该注解将被包含在javadoc中

@Inherited:说明子类可以继承父类中的该注解

@Configuration、@EnableAutoConfiguration、@ComponentScan这三个注解比较重要

@Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration):

这里的@Configuration对我们来说不陌生,它就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。

@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl(dependencyService());
    }
    
    @Bean
    public DependencyService dependencyService(){
        return new DependencyServiceImpl();
    }
}
           

@EnableAutoConfiguration:

Spring框架有提供各种名字为@Enable开头的Annotation定义,比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其实一脉相承,简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。

例如:

@EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。

@EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。

而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!

@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 {};
}
           
其中比较关键的是@Import(EnableAutoConfigurationImportSelector.class),该类的selectImports方法中调用的getCandidateConfigurations方法中,使用了SpringFactoriesLoader.loadFactoryNames方法,SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。即Spring会根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类,如下所示:
SpringApplication解读(一):注解

@EnableAutoConfiguration自动配置的本质:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

@ComponentScan:

@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。

注:所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。

继续阅读