前言:SpringBoot中提供了很多Enable開頭的注解,這些注解都是用於動態啟用某些功能的。其底層原理是使用@Import注解導入一些配置類,實現Bean的動態加載。所以,SpringBoot的自動配置,就是依賴於各種Enable開頭的注解,而Enable開頭的注解,又依賴於@Import注解實現的。
首先,我們來看SpringBoot引導類上的注解@SpringBootApplication,進一步了解引導類中使用的Enable開頭的注解。
@SpringBootApplication
public class SpringbootConfigApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootConfigApplication.class, args);
}
}
進入@SpringBootApplication注解中,可以看到,除了三個元注解(元注解這里不解釋了,固定用法,所有的注解都包含這三個注解),主要起作用的其它注解,分別解釋。
一、@Inherited注解:這個注解的作用可以自己看,講的很詳細,也有示例。鏈接:https://www.jianshu.com/p/7f54e7250be3 ,主要作用是
①、類繼承關系中@Inherited的作用:類繼承關系中,子類會繼承父類使用的注解中被@Inherited修飾的注解
②、接口繼承關系中@Inherited的作用:接口繼承關系中,子接口不會繼承父接口中的任何注解,不管父接口中使用的注解有沒有被@Inherited修飾
③、類實現接口關系中@Inherited的作用:類實現接口時不會繼承任何接口中定義的注解
二、@SpringBootConfiguration注解的作用,先進入該注解中,發現該注解就是聲明一個配置類,因此,在SpringBoot引導類中,我們也可以定義Bean。
三、@EnableAutoConfiguration注解,進入該注解中,可以發現,其最終是使用了@Import注解,導入一些配置
四、@ComponentScan注解作用:組件掃描。掃描范圍:當前引導類所在包及其子包。
綜上,@SpringBootApplication注解,依賴的最重要注解就是@EnableAutoConfiguration,及間接依賴的@Import注解。
下面我們做一個示例:驗證SpringBoot工程能否直接獲取jar包中定義的Bean
一、首先,我們新建一個SpringBoot工程springboot-enable,獲取user的Bean
@SpringBootApplication
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
二、再新建一個SpringBoot工程springboot-enable-user,定義User實體類和User配置類
User實體類
/**
* @description:user實體類
* @date: 2020/10/10 10:29
* @author: winson
*/
public class User {
}
User配置類
/**
* @description:User配置類
* @date: 2020/10/10 10:29
* @author: winson
*/
@Configuration
public class UserConfig {
@Bean
public User user() {
return new User();
}
}
三、在springboot-enable工程中,導入springboot-enable-user工程的依賴
<dependency>
<groupId>com.winson</groupId>
<artifactId>springboot-enable-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
四、啟動程序,測試user是否注入到了IOC容器中。
結論:SpringBoot工程不能直接獲取jar包中定義的Bean
接着上述結果,說明為什么不能直接獲取jar包中定義的Bean,這跟引導類@SpringBootApplication注解上的@ComponentScan注解有關系,上述提到了該注解,其掃描范圍為引導類所在的包及其子包,而上述測試用的User配置類並不在這個范圍內,所以無法獲取到。
引導類所在的包為:com.winson.springbootenable
User配置類所在的包為:com.winson.config
下面就上述問題,給出答案,實現SpringBoot工程可以獲取jar包中定義的Bean
方法一、使用@ComponentScan注解,將User配置類所在包,加入掃描范圍
修改引導類,加入@ComponentScan注解,將User配置類所在包,加入掃描范圍
@SpringBootApplication
@ComponentScan("com.winson.config")
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
測試結果:可以發現這時可以獲取user的Bean。
方法二、使用@Import注解,將User配置類導入到引導類中
@SpringBootApplication
@Import(UserConfig.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
測試結果:也可以獲取user的Bean。
方法三、對@Import注解進行封裝
一、新建一個注解類@EnableUser,使用@Import導入User配置類UserConfig
/**
* @description:封裝@Import注解
* @date: 2020/10/10 11:20
* @author: winson
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}
二、在引導類中,使用@EnableUser注解
@SpringBootApplication
@EnableUser
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
三、啟動程序,測試結果:也可以獲取user的Bean。