首先咱們分析的就是入口類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