首先咱们分析的就是入口类Application
的启动注解@SpringBootApplication
,进入源码:html
@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
。java
@SpringBootConfiguration
继承自@Configuration
,两者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean
注解标记的方法的实例归入到srping
容器中,而且实例名就是方法名。@EnableAutoConfiguration
的做用启动自动的配置,@EnableAutoConfiguration
注解的意思就是Springboot
根据你添加的jar包来配置你项目的默认配置,好比根据spring-boot-starter-web
,来判断你的项目是否须要添加了webmvc
和tomcat
,就会自动的帮你配置web项目中所须要的默认配置。在下面博客会具体分析这个注解,快速入门的demo实际没有用到该注解。@ComponentScan
,扫描当前包及其子包下被@Component
,@Controller
,@Service
,@Repository
注解标记的类并归入到spring容器中进行管理。是之前的<context:component-scan>
(之前使用在xml中使用的标签,用来扫描包配置的平行支持)。因此本demo中的User为什么会被spring
容器管理。
根据上面的理解,上面的入口类Application
,咱们可使用:web
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
也能够归入到容器管理。spring
- 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容器中,tomcat
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(); } }
启动启动类,打印结果以下:springboot
说明Cat类并无归入到spring容器中,这个结果也如咱们所想,由于@SpringBootApplication只会扫描@SpringBootApplication注解标记类包下及其子包的类(特定注解标记,好比说@Controller,@Service,@Component,@Configuration和@Bean注解等等)归入到spring容器,很显然MyConfig不在@SpringBootApplication注解标记类相同包下及其子包的类,因此须要咱们去配置一下扫包路径。mvc
修改启动类,@SpringBootApplication(scanBasePackages = "com.zhihao.miao"),指定扫描路径:spring-boot
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); } }
启动并打印:spa
固然使用@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