16-SpringBoot自动配置-Enable注解原理
Enable注解原理
@Enable* 注解
SpringBoot提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用 @Import 注解导入一些配置类,实现 Bean 的动态加载。
思考
SpringBoot工程是否可以直接获取在其他工程定义的 bean 呢?
下面我们创建两个工程来演示一下:
- 一个工程演示如何获取其他工程定义的bean
- 一个工程编写 bean
案例
1.创建 springboot-enable 工程:用来获取其他工程的 bean
2.创建 springboot-enable-other 工程:用来定义 bean
3.【springboot-enable-other】定义 bean
编写 User 类 以及 返回 User bean 对象的配置类
User:
package com.lijw.springbootenableother.domain;
public class User {
}
UserConfig:
package com.lijw.springbootenableother.config;
import com.lijw.springbootenableother.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
4.【springboot-enable】引入 【 springboot-enable-other】的工程依赖
<!-- 引入 springboot-enable-other -->
<dependency>
<groupId>com.lijw</groupId>
<artifactId>springboot-enable-other</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
5.【springboot-enable】获取 【 springboot-enable-other】工程的 User类 bean
代码如下:
package com.lijw.springbootenable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootEnableApplication {
public static void main(String[] args) {
// 获取IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
// 其他工程
Object user = context.getBean("user");
System.out.println(user);
}
}
从结果来看获取不到 user 的 bean 对象,那么为什么会获取不到呢?
让我们进入一下@SpringBootApplication的注解,如下:
SpringBoot的应用注解默认只会扫描 应用引导类下的包:
如果希望扫描其他工程的 bean,那么可以增加扫描包的范围。
6.【springboot-enable】增加扫描其他工程的包
@SpringBootApplication
@ComponentScan("com.lijw.springbootenableother.config")
public class SpringbootEnableApplication {
虽然按照上面的方法,我们已经可以扫描其他工程的类了,但是如果类特别多,这种写法是很不方便的。
我们可以修改一下,采用 @Import 配置类的方式
7.【springboot-enable】使用 @Import 直接导入其他工程的配置类,获取 bean
@Import(UserConfig.class)
这样我们也可以获取到配置类中的 bean,虽然比之前扫描包要好,但是如果每次需要这样导入配置类,还是很不方便的。
有没有办法让第三方工程自己定义好注解,我使用的时候直接添加个注解就可以了呢?
这时候我们可以写一个 @Enable* 注解。
8.【springboot-enable-other】定义 @EnableUser 注解类
package com.lijw.springbootenableother.config;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}
我们在 @EnableUser 中添加 @Import 配置类的内容,这样就不用让引入工程去写了。
9.【springboot-enable】使用 @EnableUser 导入其他工程的配置类,获取 bean
小结
SpringBoot应用默认扫描不到其他工程的 bean
原因:@ComponentScan 扫描范围:当前引导类所在包及其子包
三种解决方案:
1.使用@ComponentScan扫描第三方工程的包
2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器
3.可以对Import注解进行封装。
重点:Enable注解底层原理是使用@Import注解实现Bean的动态加载