Spring Boot @Enable注解与@Import原理
@Enable* 注解是 Spring 模块化配置的核心机制。
@Enable注解示例
Java
@EnableScheduling // 开启定时任务
@EnableAsync // 开启异步
@EnableCaching // 开启缓存
@EnableTransactionManagement // 开启事务
@Import三种使用方式
1. 导入普通类
Java
@Import(UserService.class)
@Configuration
public class AppConfig {
// UserService被注册为Bean
}
2. 导入ImportSelector
Java
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 根据条件返回要导入的类名
return new String[]{
"com.example.UserService",
"com.example.OrderService"
};
}
}
@Import(MyImportSelector.class)
@Configuration
public class AppConfig {
}
3. 导入ImportBeanDefinitionRegistrar
Java
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 动态注册Bean
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class);
builder.addPropertyValue("name", "custom");
registry.registerBeanDefinition("userService",
builder.getBeanDefinition());
}
}
@Import(MyRegistrar.class)
@Configuration
public class AppConfig {
}
自定义@Enable注解
定义注解
Java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(EnableMyFeatureRegistrar.class)
public @interface EnableMyFeature {
String[] basePackages() default {};
boolean proxyTargetClass() default false;
}
实现Registrar
Java
public class EnableMyFeatureRegistrar
implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 获取注解属性
Map<String, Object> attrs = metadata.getAnnotationAttributes(
EnableMyFeature.class.getName());
String[] packages = (String[]) attrs.get("basePackages");
// 注册扫描器
ClassPathBeanDefinitionScanner scanner =
new ClassPathBeanDefinitionScanner(registry);
scanner.scan(packages);
}
}
使用注解
Java
@SpringBootApplication
@EnableMyFeature(basePackages = "com.example.service")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Import源码解析
Java
// ImportSelector调用链
ConfigurationClassParser#processImports
→ ImportSelector#selectImports
→ 返回类名数组
→ 递归处理返回的类
// ImportBeanDefinitionRegistrar调用链
ConfigurationClassParser#processImports
→ 存储Registrar实例
→ ConfigurationClassPostProcessor#processConfigBeanDefinitions
→ Registrar#registerBeanDefinitions
ImportSelector高级用法
Java
public class ConditionalImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 判断环境
String env = System.getProperty("spring.profiles.active");
if ("prod".equals(env)) {
return new String[]{"com.example.ProdConfig"};
} else {
return new String[]{"com.example.DevConfig"};
}
}
@Override
public Predicate<String> getExclusionFilter() {
// 排除特定类
return className -> className.contains("internal");
}
}
对比总结
| 方式 | 特点 | 适用场景 |
|---|---|---|
| 直接导入类 | 简单直接 | 固定配置类 |
| ImportSelector | 条件选择 | 多配置动态选择 |
| ImportBeanDefinitionRegistrar | 完全控制 | 动态注册Bean |
@Import优先级高于@ComponentScan,在配置类解析阶段执行。
要点总结
- @Enable*注解本质是@Import的封装
- ImportSelector适合条件性导入
- Registrar适合动态注册Bean定义
- 掌握原理可实现模块化Starter
📝 发现内容有误?点击此处直接编辑