@AutoConfiguration注解详解

这篇具有很好参考价值的文章主要介绍了@AutoConfiguration注解详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

@AutoConfiguration属于springboot当中autoconfigure包下的注解。springboot给我们提供了好多AutoConfiguration,例如关于缓存cache的有CacheAutoConfiguration,关于定时任务quartz的有QuartzAutoConfiguration,这些AutoConfiguration你会发现基本上都会拿@AutoConfiguration来修饰。本篇来彻底了解@AutoConfiguration到底有什么作用,以及到底如何应用他。

一、观察@AutoConfiguration源码

源码当中有三个元注解:

  • @Target({ElementType.TYPE}): 使用范围接口、类、枚举、注解
  • @Retention(RetentionPolicy.RUNTIME): @Retention是用来修饰注解的生命周期的,RetentionPolicy.RUNTIME代表的是不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一直有效!
  • @Documented: @Documented和@Deprecated注解长得有点像,@Deprecated是用来标注某个类或者方法不建议再继续使用,@Documented只能用在注解上,如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成Javadoc文档时,会显示@B。

除了元注解外还有三个注解:

  • @Configuration: 这个是开发当中最常用的注解,他属于是@Component注解的扩展注解,同@Controller、@Service等几个注解的功能是一样的,只要在类上添加了该注解,然后在springboot的扫描范围内,启动项目的时候会将该注解修饰的类通过无参构造器创建出来,然后存入spring容器当中。
  • @AutoConfigureBefore: 一般都是配合着@Configuration使用,主要用于修饰在类上,然后可以指定该类 在 某类之前进行加载到容器。
  • @AutoConfigureAfter:@AutoConfigureBefore功能一样,他是指定该类 在 某类 之后进行加载到容器当中。

具体的用法请看下面的示例!

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(
    proxyBeanMethods = false
)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    String value() default "";

    @AliasFor(
        annotation = AutoConfigureBefore.class,
        attribute = "value"
    )
    Class<?>[] before() default {};

    @AliasFor(
        annotation = AutoConfigureBefore.class,
        attribute = "name"
    )
    String[] beforeName() default {};

    @AliasFor(
        annotation = AutoConfigureAfter.class,
        attribute = "value"
    )
    Class<?>[] after() default {};

    @AliasFor(
        annotation = AutoConfigureAfter.class,
        attribute = "name"
    )
    String[] afterName() default {};
}

@AutoConfiguration其实就是一个组合注解。因为一个自动配置类往往需要加很多注解,于是乎springboot就将一些经常用到的注解,给组合到一块,这样就可以做到一个注解拥有三个注解的功能。具体他是如何做到注解聚合到一块的呢,原因是依赖于@AliasFor注解,@AliasFor注解就是起到一个注解传值的作用。想深入了解@AliasFor可以看我的这一篇文章:

https://blog.csdn.net/weixin_43888891/article/details/126962698?spm=1001.2014.3001.5501

@AutoConfiguration注解详解

二、@Configuration

@Configuration注解我们经常用,但是我们很少这样用@Configuration(proxyBeanMethods = false),这里的proxyBeanMethods默认是true,但是这里却设置为了false,那么这个属性到底有什么作用?

@Configuration属于spring当中的注解,感兴趣的可以看一下spring源码当中的解释:https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java

源码当中解释不是中文,再者一般的也看不懂,我们直接通过代码试验来得出结论:

当他为true的时候,我们在容器中获取到的对象总是同一个,即便是我们调用了创建对象的方法,那获取到的还是同一个。但是当是多例的时候,如果我们调用了创建对象的方法,那就不是同一个了。

(1)自定义一个类,用于测试

public class TestBean1 {
    @Override
    public String toString() {
        return super.toString() + "--我是TestBean1";
    }

    public TestBean1() {
        System.out.println("TestBean1构造器执行了");
    }
}

(2)添加配置类

@Configuration(proxyBeanMethods = true)
public class Myconfig {

    @Bean
    public TestBean1 testBean1() {
        return new TestBean1();
    }
}

(3)添加测试类

@RestController
public class CommonController {

    @Autowired
    private Myconfig myconfig;

    @Autowired
    private TestBean1 testBean1;

    @RequestMapping("/import")
    public void printImportBeanInfo() {
        System.out.println(testBean1);
        System.out.println(myconfig.testBean1());
    }
}

(4)访问接口,得出从容器里面取和直接访问testBean1方法得出来的对象是一个对象,这就是所谓的被代理了

@AutoConfiguration注解详解
(5)设置为false@Configuration(proxyBeanMethods = false)

很显然已经不是一个对象了

@AutoConfiguration注解详解

三、@AutoConfigureBefore

(1)自定义两个配置类

@Configuration
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

(2)启动项目测试:默认是先创建的Config1后创建的Config2

@AutoConfiguration注解详解

现在是有个需求要求让@Config2先加载,可能这时候有人该说了@Order注解不就可以了吗,其实不是的,@Order值可能会影响注入点的优先级,但请注意,它不会影响单例启动顺序。关于@order我专门整理了一篇文章,供参考学习!
https://blog.csdn.net/weixin_43888891/article/details/127481825

(3)使用@AutoConfigure相关注解的前提是必须是自动配置类,可能有时候走了狗屎运给你一种错觉还真的配置成功了。

在Config2上添加@AutoConfigureBefore(Config1.class)注解,就是告诉他我要在Config1之前注入容器,只加入注解后再次启动项目会发现没有任何作用!

@AutoConfiguration注解详解

在autoconfigure包下就有spring.factories,这个文件配置了自动配置类,springboot会读取这个文件的,我们也可以在自己项目上定义spring.factories,这样我们的配置类对于@AutoConfigureAfter注解就可以生效了。

@AutoConfiguration注解详解
(4)自定义spring.factories

@AutoConfiguration注解详解

第一行是固定的,后面的就是全类名,虽然只有Config2使用了注解,但是需求是和Config1进行排序,所以这两个都得加。

可能有的人对这里会有疑问,我不使用@AutoConfigureBefore注解,只通过spring.factories下面的配置可以修改这两个配置类的启动顺序吗,答案是不可以的!!! 关于这一点我也通过试验印证过了!

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gzl.cn.springbootcache.config.Config2,\
com.gzl.cn.springbootcache.config.Config1

(5)测试,成功解决

@AutoConfiguration注解详解

四、@AutoConfigureAfter

@AutoConfigureAfter和@AutoConfigureBefore其实是一样的,我这里就不演示了哈,感兴趣的可以自己参照上面进行练习一下。

五、@AutoConfigureOrder

这种也是可以的!当然前提也是需要配置spring.factories

@Configuration
@AutoConfigureOrder(2)
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
@AutoConfigureOrder(1)
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

六、源码分析

其实关键的代码还是在AutoConfigurationImportSelector中,将自动配置类从spring.factories加载出来之后会根据条件排序,在selectImports()方法中最后一行代码如下:

@AutoConfiguration注解详解

紧接着会走到这个地方,实际上是分了三步排序:

  1. 先按照字母排序
  2. 按照@AutoConfigureOrder进行排序
  3. 按照 @AutoConfigureBefore和@AutoConfigureAfter排序

@AutoConfiguration注解详解
从上面配置的顺序可以知道,最终决定权还是在@AutoConfigureAfter、@AutoConfigureBefore这两个注解。

当我们不设置spring.factories的时候,这里面压根都没有这两个类!

@AutoConfiguration注解详解文章来源地址https://www.toymoban.com/news/detail-412876.html

到了这里,关于@AutoConfiguration注解详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java注解——@Override注解(详解1)

    1、注解: 注解是 JDK 1.5 的特性 注解是给编译器或 JVM 看的,编译器或 JVM 可以根据注解来完成相应的功能。 或者叫注释类型,英文是:Annotation 注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件。 注解的语法格式: 【修饰符列表】 @interface 注解类型名{ } publ

    2024年02月03日
    浏览(44)
  • EasyExcel格式化映射注解和样式注解详解

    使用注解很简单,只要在对应的实体类上面加上注解即可。 也就是说使用实体类模型来读写 Excel 文件时,可以通过注解来控制实体类字段和 Excel 列之间的对应关系。 2.1 作用 ExcelProperty 注解用于匹配 excel 和实体类字段之间的关系。 可以作用于字段上。 2.1 注解参数 名称 默

    2024年01月20日
    浏览(30)
  • @KafkaListener注解详解(一)| 常用参数详解

    @KafkaListener 注解提供了许多可配置的参数,以便更灵活地定制 Kafka 消息监听器的行为。 描述: 指定监听的 Kafka 主题,可以是一个字符串数组。这是最基本的参数,它定义了监听器将从哪个或哪些主题接收消息。 例子: @KafkaListener(topics = \\\"my-topic\\\") 描述: 指定 Kafka 消费者组

    2024年02月04日
    浏览(38)
  • @TableField注解详解

    1、@TableField(value = \\\"email\\\")//指定数据库表中字段名 如果数据库和实体类的字段名不一致,可以使用@TableField注解指定数据库表中字段名。  2、@TableField(exist = \\\"false\\\")//数据库表中不存在的数据,在实体类中指定。 如果数据库表中不存在字段,在实体类中使用@TableField注解指

    2024年02月11日
    浏览(28)
  • @EqualsAndHashCode注解详解

    首先该注解的作用: 1. 此注解会生成equals(Object other) 和 hashCode()方法。 2. 它默认使用非静态,非瞬态的属性 3. 通过参数exclude指定排除属性 4. 通过参数of指定使用的属性 5. @EqualsAndHashCode(callSuper...),callSuper默认为false,即默认不适用父类中属性判断 下面上代码说明 父

    2023年04月23日
    浏览(36)
  • @PreAuthorize注解详解

    @PreAuthorize注解会在方法执行前进行权限验证,支持Spring EL表达式,它是基于方法注解的权限解决方案。只有当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PreAuthorize才可以使用,@EnableGlobalMethodSecurity注解在SPRING安全中心进行设置,如下:   如何使用 ①. 注解如何使用? ②

    2024年02月10日
    浏览(55)
  • android 注解详解

    注解现在广泛的应用于android的各个开源框架中,不理解注解,我们就无法更好的提升我们的架构能力。那么什么是注解呢?注解(Annotation),是 JDK5.0 引入的一种注释机制。 注解是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对它们注解的代码的操作

    2024年02月09日
    浏览(27)
  • @Transactional 注解使用详解

    @Transactional 的作用范围 方法 :推荐将注解使用于方法上,不过需要注意的是: 该注解只能应用到 public 方法上,否则不生效。 类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。 接口 :不推荐在接口上使用。 @Transactional 的常用配置参数总结

    2023年04月11日
    浏览(70)
  • 详解SpringBoot的常用注解

    在SpringBoot中,注解是一种非常重要的编程方式,它可以简化代码,提高开发效率。本文将详细介绍SpringBoot中的常用注解,以及它们的使用方法和场景。 1.1 概述 @SpringBootApplication 是SpringBoot应用程序的核心注解,通常用于主类上。它包含了以下三个注解: @Configuration :表示该

    2024年02月13日
    浏览(86)
  • SpringBoot - @Transactional注解详解

    简介 Spring中的@Transactional注解,基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷的解决在开发中碰到的问题,@Transactional 的事务开启 ,或者是基于接口的或者是基于类的代理被创建。Spring为了更好的支撑数据库操作,在框架中支持了两种事务管理的方式:编

    2024年02月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包