SpringBoot源码解析

1.@SpringBootApplication

springboot采用注解方式开发的,当创建了一个springboot项目时,在启动类上会有一个注解@SpringBootApplication,这个注解用来标识是一个springboot的项目,并且此类是启动类。

进入@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 {

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     * @return the classes to exclude
     */
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {};

    /**
     * Exclude specific auto-configuration class names such that they will never be
     * applied.
     * @return the class names to exclude
     * @since 1.3.0
     */
    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};

    /**
     * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
     * for a type-safe alternative to String-based package names.
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};

    /**
     * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
     * scan for annotated components. The package of each class specified will be scanned.
     * <p>
     * Consider creating a special no-op marker class or interface in each package that
     * serves no purpose other than being referenced by this attribute.
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

}

先看@Target:

2.一级注解

2.1@Target

作用是指定注解的使用范围。其源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

在这个注解里面就定义了一个枚举类型的数组,其枚举类型如下:

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

表示的意义见表格:

类型 说明 用法
TYPE 表明此注解只能用于接口、类上

@Target(ElementType.TYPE)

 FIELD  表明此注解只能用于字段上  @Target(ElementType.FIELD)
 METHOD 表明此注解只能用于方法上   @Target(ElementType.METHOD) 
 PARAMETER 表明此注解只能用于方法参数上   @Target(ElementType.PARAMETER) 
 CONSTRUCTOR 表明此注解只能用于构造函数上   @Target(ElementType.CONSTRUCTOR) 
 LOCAL_VARIABLE 表明此注解只能用于局部变量上   @Target(ElementType.LOCAL_VARIABLE) 
 ANNOTATION_TYPE 表明此注解只能用于注解上   @Target(ElementType.ANNOTATION_TYPE) 
 PACKAGE 表明此注解只能用于包上   @Target(ElementType.PACKAGE) 
 TYPE_PARAMETER 表明此注解只能用于类型参数上   @Target(ElementType.TYPE_PARAMETER) 
 TYPE_USE 表明此注解只能用于任何类型上   @Target(ElementType.TYPE_USE) 

再回到上面的源码,@Target(ElementType.TYPE)也就指定了注解只能用于接口、类上。

2.2.@Retention

作用是指定注解的保留位置。其源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

注解中定义了一个枚举,源码如下:

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

其中

SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;

CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;

RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,即在运行时也存在。

那么源码中的注解就表示在运行时此注解也存在。

2.3@Documented

作用是指定自定义的注解是否能随着被定义的java文件生成到JavaDoc文档当中。那么源码中的注解就表示注解会生成到JavaDoc文档中。

2.4@Inherited

作用是只有用在类上时,会被子类继承此自定义的注解。也就是说当@Inherited注解加在某个类A上时,假如类B继承了A,则B也会带上该注解。那么源码中的注解就表示定义的注解被继承时子类也有父类的这些注解。

2.5@SpringBootConfiguration

其继承自@Configuration,表明当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。那么源码中的注解就表示当前的注解是一个SpringBoot的配置类。

2.6@EnableAutoConfiguration

作用是开启允许自动配置,这样spring会帮我们自动配置。主要源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
     ....              
}

红色的注解在二级注解中介绍。

2.7@ComponentScan

作用是定义扫描的路径并从中找出标识了需要装配的类自动装配到spring的bean容器中,简单的说,就是把指定的类交给spring来管理。会被自动装配的注解包括@Controller、@Service、@Component、@Repository等等。那么源码中的注解就是扫描启动类所在的包以及下面的包。

3.二级注解

3.1@Import

作用是给容器中导入一个组件。那么源码中的注解作用是将所有需要导入的组件以全类名的方式返回并自动导入所有符合自动配置条件的Bean定义并加载到IOC容器。

3.2@AutoConfigurationPackage

作用是自动配置包,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

@Import指定导入的组件由AutoConfigurationPackages.Registrar.class将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器。

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。

原文地址:https://www.cnblogs.com/zys2019/p/13848141.html