SpringBootApplication是一个复合注解,包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration。
1 @SpringBootConfiguration
SpringBootConfiguration注解是spring boot中的配置注解类。它继承自spring中的Configuration配置注解类。
1.1 @Configuration注解
Configuration是spring的配置注解类,用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
1.1.1使用
@SpringBootConfiguration
@ComponentScan("com.example.springbootdemo") //
public class Configuration {
    @Bean(initMethod = "initMethod")
    public Piano piano(){
        return new Piano();
    }
    @Bean
    public Harmonica harmonica(){
        piano();//测试SpringBootConfiguration类对BEAN只实例化一次
        return new Harmonica();
    }
}
启动类:
public class SpringbootDemoApplication {
//    public static void main(String[] args) {
//        SpringApplication.run(SpringbootDemoApplication.class, args);
//    }
    public static void main(String[] args) {
        ApplicationContext annotationContext = new AnnotationConfigApplicationContext(Configuration.class);
        ApplicationContext annotationContext = new AnnotationConfigApplicationContext(Configuration.class);
        System.out.println(annotationContext.getBean(Piano.class));
        System.out.println(annotationContext.getBean(Piano.class));
    }
}
执行结果:
image.png
从打印结果来看,Piano类只被实例化了一次。现将Confinguration类的@SpringBootConfiguration注销,再执行代码,运行结果如下:
image.png
从运行结果看,Piano类被实例化了两次。
结论:@SpringBootConfiguration注解实例化为单例模式
1.1.2 Configuration注释的类会被CGLIB代理
验证过程:
Configuraion未加@Configuration注解
//@SpringBootConfiguration
@ComponentScan("com.example.springbootdemo") //
public class Configuration {
    @Bean(initMethod = "initMethod")
    public Piano piano(){
        return new Piano();
    }
    @Bean
    public Harmonica harmonica(){
        piano();//测试SpringBootConfiguration类对BEAN只实例化一次
        return new Harmonica();
    }
}
main方法
    public static void main(String[] args) {
        ApplicationContext annotationContext = new AnnotationConfigApplicationContext(Configuration.class);
        System.out.println(annotationContext.getBean(Configuration.class));
//        System.out.println(annotationContext.getBean(Piano.class));
//        System.out.println(annotationContext.getBean(Piano.class));
    }
执行后返回结果:
image.png
Configuration加上@Configuration注解
@SpringBootConfiguration
//@ComponentScan("com.example.springbootdemo") //
public class Configuration {
    @Bean(initMethod = "initMethod")
    public Piano piano(){
        return new Piano();
    }
    @Bean
    public Harmonica harmonica(){
        piano();//测试SpringBootConfiguration类对BEAN只实例化一次
        return new Harmonica();
    }
}
再次执行main方法,返回结果如下:
image.png
结论:通过@Configuration注解的类会被CGLIB代理
注意:@Configuration注解的配置类有如下要求:
1.@Configuration不可以是final类型;
2.@Configuration不可以是匿名类;
3.嵌套的configuration必须是静态类。
1.1.2 源码分析
在Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostPRocessor,其中 ConfigurationClassPostProcessor这个后置处理器专门处理带有@Configuration注解的类,ConfigurationClassPostProcessor后置处理实现了BeanDefinitionRegistryPostProcessor接口和PriorityOrdered接口,所以会在容器初始化refres()方法中执行后置处理器时优先执行,主要负责解析所有@Configuration标签类,并将Bean定义注册到容器中。











网友评论