SpringBoot基本注解

【SpringBoot】

@SpringBootApplication(启动类注解)

@SpringBootConfiguration

标注在类上,表示对配置类所有成员生效。是@Configuration注解的派生注解,跟@Configuration注解的功能一致,标注这个类是一个配置类,只不过@SpringBootConfiguration是springboot的注解,而@Configuration是spring的注解。

@Target

注解的作用目标 :

@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)——包

@Retention

注解的保留位置:

RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

@Document

说明该注解将被包含在javadoc

@Inherited

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

当@InheritedAnno注解加在某个类A上时,假如类B继承了A,则B也会带上该注解。

@EnableAutoConfiguration(自动配置)

借助@Import的支持,收集和注册特定场景相关的bean定义

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

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

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

其中,最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。就像一只“八爪鱼”一样

借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成!

工具类SpringFactoriesLoader

自动配置幕后英雄:SpringFactoriesLoader详解
SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置,配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wEi0H73U-1612921729325)(.\image@EnableAutoConfiguration.jpg)]

上图就是从SpringBoot的autoconfigure依赖包中的META-INF/spring.factories配置文件中摘录的一段内容,可以很好地说明问题。

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

@ComponentScan

@ComponentScan(excludeFilters = {

		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),

		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

1、@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素。

@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

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

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

2、@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。

例如,如果你有个类用@Controller注解标识了,那么,如果不加上@ComponentScan,自动扫描该controller,那么该Controller就不会被spring扫描到,更不会装入spring容器中,因此你配置的这个Controller也没有意义。

3、参数的作用

  1. basePackageClasses:对basepackages()指定扫描注释组件包类型安全的替代。
  2. excludeFilters:指定不适合组件扫描的类型。
  3. includeFilters:指定哪些类型有资格用于组件扫描。
  4. lazyInit:指定是否应注册扫描的beans为lazy初始化。
  5. nameGenerator:用于在Spring容器中的检测到的组件命名。
  6. resourcePattern:控制可用于组件检测的类文件。
  7. scopedProxy:指出代理是否应该对检测元件产生,在使用过程中会在代理风格时尚的范围是必要的。
  8. scopeResolver:用于解决检测到的组件的范围。
  9. useDefaultFilters:指示是否自动检测类的注释

@Import与@ImportSource区别

对于**@Import@ImportResource**这两个注解想必大家并不陌生。我们会经常用@Import来导入配置类或者导入一个带有@Component等注解要放入Spring容器中的类用@ImportResource来导入一个传统的xml配置文件。另外,在启用很多组件时,我们会用到一个形如@EnableXXX的注解,比如@EnableAsync、@EnableHystrix、@EnableApollo等,点开这些注解往里追溯,你也会发现@Import的身影。如此看来,这两个注解与我们平时的开发关系密切,但大家知道它们是如何发挥作用的吗?下面就一起探索一下。

对parse.parse()方法的调用:

          // 初始化解析器
          ConfigurationClassParser parser = new ConfigurationClassParser(
                  this.metadataReaderFactory, this.problemReporter, this.environment,
                  this.resourceLoader, this.componentScanBeanNameGenerator, registry);
          Set<BeanDefinitionHolder> candidates = 
              new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
          Set<ConfigurationClass> alreadyParsed = 
              new HashSet<ConfigurationClass>(configCandidates.size());
          do {
             // 解析,此方法是这个后置处理方法的核心   经过了漫长的解析 复杂的一批
             parser.parse(candidates);

此方法异常复杂,但是这不能阻挡我们前进的脚步,继续查看之。发现后面调到了org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass方法,此方法内容量较大,分别对@PropertySource、@Import、@ImportSource、@Bean进行了处理,我们就以@ImportResource为例追溯,因为@Import相比@ImportResource只是少了一步解析Xml文件。

定位到处理@ImportResource的地方:

         // 将解析结果添加到ConfigurationClass的importedResources中
         if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
             AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor
                  (sourceClass.getMetadata(), ImportResource.class);
             String[] resources = importResource.getAliasedStringArray("locations", 
                   ImportResource.class, sourceClass);
             Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
             for (String resource : resources) {
                 String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                 configClass.addImportedResource(resolvedResource, readerClass);
             }
         }

可以知道,此处是将@ImportResource中每一个xml资源配置项提取出来,跟reader一起放入了configClass的一个map中。有放入就有取出,取出的地方在parse方法的下面,如下所示:

取出放入configClass中(由@ImportResource标注的)每一个xml资源配置:

  parser.parse(candidates);
           parser.validate();       
			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>					
                (parser.getConfigurationClasses());
        	configClasses.removeAll(alreadyParsed);

        	// Read the model and create bean definitions based on its content
        	if (this.reader == null) {
            	this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        	}
        	// 将BeanDefinition加载进容器中
        	this.reader.loadBeanDefinitions(configClasses);

第14行代码点进去追溯,就会发现下面的方法:

   private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
            TrackedConditionEvaluator trackedConditionEvaluator) {
 
      if (trackedConditionEvaluator.shouldSkip(configClass)) {
           String beanName = configClass.getBeanName();
           if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                this.registry.removeBeanDefinition(beanName);
           }
           this.importRegistry.removeImportingClassFor(configClass.getMetadata().getClassName());
           return;
       }
       if (configClass.isImported()) {
           registerBeanDefinitionForImportedConfigurationClass(configClass);
       }
       for (BeanMethod beanMethod : configClass.getBeanMethods()) {
           loadBeanDefinitionsForBeanMethod(beanMethod);
       }
       loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
       loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
  }

第19行代码处就是取出了之前put进去的数据,调用XmlBeanDefinitionReader的loadBeanDefinitions方法进行载入处理。而且此处还可以看到对@Import的处理,对ImportBeanDefinitionRegistrars的处理。

到这里,Spring容器就完成了对@Import、@ImportResource注解的处理,将所有涉及到的类都存入了容器中。其中还有一点需要提一下,就是在对@Import注解处理的时候,使用了递归跟循环调用,因为@Import引入的类上可能还有@Import、@ImportResource等注解,这样做就能保证不会漏掉。

@Component与@Configuration区别

@Component 和 @Bean 是两种使用注解来定义bean的方式。

@Component使用类路径扫描自动检测和配置bean,而@Bean显式地声明了一个bean,而不是让Spring自动做这项工作。

@Component使用类本身,而@Bean使用类方法(产生类对象的实例)。

@Component不会将bean的声明从类定义解耦,而@Bean会将bean的声明从类定义解耦。

@Component是类级别的注释,而@Bean是方法级别的注释,方法的名称充当bean的名称。

@Component不需要与@Configuration注释一起使用,因为@Bean注释必须在类中使用

  1. @Component(以及@Service和@Repository)用于使用类路径扫描自动检测和自动配置bean。在带注释的类和bean之间存在隐式的一对一映射(即每个类一个bean)。这种方法对连接的控制非常有限,因为它是纯粹的声明性的。

    这种方法对需要进行逻辑处理的控制非常有限,因为它纯粹是声明性的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDU3UrH3-1612921729333)(.\image@Component.png)]

  1. @Bean`用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离(解耦),并允许您精确地创建和配置bean.

    而@Bean则常和@Configuration注解搭配使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TUc4wi7v-1612921729336)(.\image@Configeration&2Bean.png)]

  • 都可以使用@Autowired或者@Resource注解注入

@EnableWebMvc

弃用SpringBoot对SpringMVC提供的自动配置功能

Spring Boot为Spring MVC提供适用于多数应用的自动配置功能。在Spring默认基础上,自动配置添加了以下特性:

  1. 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
  2. 对静态资源的支持,包括对WebJars的支持。
  3. 自动注册Converter,GenericConverter,Formatter beans。
  4. 对HttpMessageConverters的支持。
  5. 自动注册MessageCodeResolver。
  6. 对静态index.html的支持。
  7. 对自定义Favicon的支持。

如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc对其注解。如果想保留Spring Boot MVC的特性,并只是添加其他的MVC配置(拦截器,formatters,视图控制器等),你可以添加自己的WebMvcConfigurerAdapter类型的@Bean(不使用@EnableWebMvc注解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值