zoukankan      html  css  js  c++  java
  • @SpringBootApplication注解分析

    首先我们分析的就是入口类Application的启动注解@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 {
    ....
    }
    复制代码

    发现@SpringBootApplication是一个复合注解,包括@ComponentScan,和@SpringBootConfiguration@EnableAutoConfiguration

    • @SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到srping容器中,并且实例名就是方法名。
    • @EnableAutoConfiguration的作用启动自动的配置,@EnableAutoConfiguration注解的意思就是Springboot根据你添加的jar包来配置你项目的默认配置,比如根据spring-boot-starter-web ,来判断你的项目是否需要添加了webmvctomcat,就会自动的帮你配置web项目中所需要的默认配置。在下面博客会具体分析这个注解,快速入门的demo实际没有用到该注解。
    • @ComponentScan,扫描当前包及其子包下被@Component@Controller@Service@Repository注解标记的类并纳入到spring容器中进行管理。是以前的<context:component-scan>(以前使用在xml中使用的标签,用来扫描包配置的平行支持)。所以本demo中的User为何会被spring容器管理。

    根据上面的理解,上面的入口类Application,我们可以使用:

    package com.zhihao.miao;
    import com.zhihao.miao.bean.User;
    import org.springframework.boot.SpringApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import java.util.Map;
    
    @ComponentScan
    public class Application {
    
        @Bean
        public Runnable createRunnable(){
            return () -> System.out.println("spring boot is running");
        }
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
            context.getBean(Runnable.class).run();
            System.out.println(context.getBean(User.class));
            Map map = (Map) context.getBean("createMap");
            int age = (int) map.get("age");
            System.out.println("age=="+age);
    
        }
    }

    使用@ComponentScan注解代替@SpringBootApplication注解,也可以正常运行程序。原因是@SpringBootApplication中包含@ComponentScan,并且springboot会将入口类看作是一个@SpringBootConfiguration标记的配置类,所以定义在入口类Application中的Runnable也可以纳入到容器管理。

    SpringBootApplication参数详解


    图片.png
    • Class<?>[] exclude() default {}:
      根据class来排除,排除特定的类加入spring容器,传入参数value类型是class类型。
    • String[] excludeName() default {}:
      根据class name来排除,排除特定的类加入spring容器,传入参数value类型是class的全类名字符串数组。
    • String[] scanBasePackages() default {}:
      指定扫描包,参数是包名的字符串数组。
    • Class<?>[] scanBasePackageClasses() default {}:
      扫描特定的包,参数类似是Class类型数组。

    看一个demo学会使用这些参数配置
    在包下com.zhihao.miao.springboot定义一个启动应用类(加上@SpringBootApplication注解)

    package com.zhihao.miao.springboot;
    
    
    import com.zhihao.miao.beans.Cat;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
            Cat cat = context.getBean(Cat.class);
            System.out.println(cat);
        }
    }

    在com.zhihao.miao.beans包下定义一个实体类,并且想将其纳入到spring容器中,

    public class Cat {
    }
    package com.zhihao.miao.beans;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyConfig {
    
        @Bean
        public Cat cat(){
            return new Cat();
        }
    
    }

    启动启动类,打印结果如下:


     

    说明Cat类并没有纳入到spring容器中,这个结果也如我们所想,因为@SpringBootApplication只会扫描@SpringBootApplication注解标记类包下及其子包的类(特定注解标记,比如说@Controller,@Service,@Component,@Configuration和@Bean注解等等)纳入到spring容器,很显然MyConfig不在@SpringBootApplication注解标记类相同包下及其子包的类,所以需要我们去配置一下扫包路径。

    修改启动类,@SpringBootApplication(scanBasePackages = "com.zhihao.miao"),指定扫描路径:

    package com.zhihao.miao.springboot;
    
    import com.zhihao.miao.beans.Cat;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication(scanBasePackages = "com.zhihao.miao")
    public class Application {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
            Cat cat = context.getBean(Cat.class);
            System.out.println(cat);
        }
    }

    启动并打印:


     

    当然使用@SpringBootApplication(scanBasePackageClasses = MyConfig.class),指定scanBasePackageClasses参数的value值是你需要扫描的类也可以,结果一样,不过如果多个配置类不在当前包及其子包下,则需要指定多个。

    再看一个列子,
    在上面的列子的相同包下(com.zhihao.miao.springboot)配置了People,并将其纳入到spring容器中(@Component),我们知道@SpringBootApplication注解会扫描当前包及其子包,所以People类会纳入到spring容器中去,我们需要将其排除在spring容器中,如何操作?
    可以使用@SpringBootApplication的另外二个参数(exclude或excludeName)

    package com.zhihao.miao.springboot;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class People {
    }

    启动类,

    package com.zhihao.miao.springboot;
    
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
            People people = context.getBean(People.class);
            System.out.println(people);
        }
    }

    启动并打印结果:


     

    然后修改@SpringBootApplication配置,

    package com.zhihao.miao.springboot;
    
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication(exclude = People.class)
    public class Application {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
            People people = context.getBean(People.class);
            System.out.println(people);
        }
    }

    很明显启动报错。使用@excludeName注解也可以。如下,
    @SpringBootApplication(excludeName = {"com.zhihao.miao.springboot.People"})

    参考文档:
    Springboot1.5.4官方文档

    原文地址:https://www.cnblogs.com/duanxz/p/3756364.html

  • 相关阅读:
    DirectX:在graph自己主动连线中增加自己定义filter(graph中遍历filter)
    C3P0数据库连接池使用
    POJ
    【jQuery】复选框的全选、反选,推断哪些复选框被选中
    BestCoder Round #75 King&#39;s Cake 模拟&amp;&amp;优化 || gcd
    《Javascript_Dom 编程艺术》(第2版)读书笔记
    POJ 2947-Widget Factory(高斯消元解同余方程式)
    MFC 小知识总结四
    迭代器和iter()函数
    hdu1595find the longest of the shortest 最短路
  • 原文地址:https://www.cnblogs.com/technology-huangyan/p/10110070.html
Copyright © 2011-2022 走看看