首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

SpringBoot源码解析

2021-03-29 来源:华拓网
SpringBoot源码解析

1.@SpringBootApplicationspringboot采⽤注解⽅式开发的,当创建了⼀个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. *

* 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 FIELD METHOD PARAMETER CONSTRUCTOR LOCAL_VARIABLE ANNOTATION_TYPE

PACKAGE TYPE_PARAMETER

TYPE_USE

说明

表明此注解只能⽤于接⼝、类上 表明此注解只能⽤于字段上表明此注解只能⽤于⽅法上 表明此注解只能⽤于⽅法参数上 表明此注解只能⽤于构造函数上 表明此注解只能⽤于局部变量上 表明此注解只能⽤于注解上 表明此注解只能⽤于包上 表明此注解只能⽤于类型参数上 表明此注解只能⽤于任何类型上

⽤法

@Target(ElementType.TYPE) @Target(ElementType.FIELD) @Target(ElementType.METHOD) @Target(ElementType.PARAMETER) @Target(ElementType.CONSTRUCTOR) @Target(ElementType.LOCAL_VARIABLE) @Target(ElementType.ANNOTATION_TYPE)

@Target(ElementType.PACKAGE) @Target(ElementType.TYPE_PARAMETER)

@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指定的值,将这些值作为⾃动配置类导⼊到容器中,⾃动配置类就⽣效,帮我们进⾏⾃动配置⼯作。

因篇幅问题不能全部显示,请点此查看更多更全内容