注解
@SpringBootApplication 表示一个配置类:它声明一个或多个@Bean 方法,同时触发自动配置和组件扫描。这是一个组合注解相当于声明了@Configuration、@EnableAutoConfiguration 和@ComponentScan
@SoringBootApplication 三个注解
@interface 准确的说它不是一个接口,而是一个新的注释类型-注释类,它的类名就是注释名
@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();
}
官方文档注释:
@Target 官方注释
它的意思是说,用了@Target 注解的注解,可以被用在哪些作用域中,有哪些作用域需要到java.lang.annotation.ElementType 里面去找
public enum ElementType {
/** 用在描述类、接口(包括注解类型)或枚举 */
TYPE,
/** 用在字段声明(包括枚举) */
FIELD,
/** 用于方法上 */
METHOD,
/** 用在参数上 */
PARAMETER,
/** 用在构造器(又叫构造方法)上 */
CONSTRUCTOR,
/** 用在局部变量上 */
LOCAL_VARIABLE,
/** 用在描述注释上 */
ANNOTATION_TYPE,
/** 用在包上 */
PACKAGE,
/** 从1.8开始支持,自定义类型参数上 */
TYPE_PARAMETER,
/** 从1.8开始支持,对类型注解 */
TYPE_USE
}
@Retention
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.2 @Retention
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
官方文档注释:@Retention 官方注释
@Retention 是定义该注解的生命周期有多久 ,而决定它的生命周期在一个枚举类型的RetentionPolicy里
RetentionPolicy
- SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释,在.class文件中不会保留注解信息
- CLASS:在class文件中有效(即class保留),保留在.class文件中,但是当运行Java程序时,他就不会继续加载了,不会保留在内存中,JVM不会保留注解。如果注解没有加Retention元注解,那么相当于默认的注解就是这种状态。
- RUNTIME:在运行时有效(即运行时保留),当运行 Java程序时,JVM会保留注释,加载在内存中了,那么程序可以通过反射获取该注释。
@Documented (很少)
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
官方文档注释:
@Documented 官方注释
用于指定被该元注解修饰的注解类将被javadoc工具提取成文档。默认情况下,javadoc是 不包括注解的,但是加上了这个注解生成的文档中就会带着注解了。 @Documented 注释只是用来生成文档的,不重要
@Inherited(极少)
/**
* Indicates that an annotation type is automatically inherited. If
* an Inherited meta-annotation is present on an annotation type
* declaration, and the user queries the annotation type on a class
* declaration, and the class declaration has no annotation for this type,
* then the class's superclass will automatically be queried for the
* annotation type. This process will be repeated until an annotation for this
* type is found, or the top of the class hierarchy (Object)
* is reached. If no superclass has an annotation for this type, then
* the query will indicate that the class in question has no such annotation.
*
* <p>Note that this meta-annotation type has no effect if the annotated
* type is used to annotate anything other than a class. Note also
* that this meta-annotation only causes annotations to be inherited
* from superclasses; annotations on implemented interfaces have no
* effect.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.3 @Inherited
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
官方文档注释:
@Inherited 官方注释
被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。
自动装配原理
自动配置好Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.6.6</version>
<scope>compile</scope>
</dependency>
自动配置好SpringMVC
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
<scope>compile</scope>
</dependency>
自动配置好Web常见功能:
查看IOC容器组件
- 默认的包结构(约定大于配置)
PS:可以扩大自动扫包的扩大范围
- 各种配置拥有默认值
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
- 按需加载所有自动配置项
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure
组件添加
@Configuration
- 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
- 配置类本身也是组件
- proxyBeanMethods:代理bean的方法
- Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
- Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
- 组件依赖必须使用Full模式默认。其他默认是否Lite模式
自动配置原理
引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{
}
1、@SpringBootConfiguration
2、@ComponentScan
3、@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
按需开启自动配置项
修改默认配置
给容器中加入了文件上传解析器:传入的名称不叫multipartResolver,通过multipartResolver方法给它返回正确的名称
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
// 容器中没有这个名字 multipartResolver 的组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}