09.2 — @Configuration 增强与 @Import
←**返回 进阶源码索引**
1. @Configuration CGLIB 增强 — Full vs Lite 模式
Full 模式
java
@Configuration // Full 模式 — CGLIB 增强
public class AppConfig {
@Bean
public A a() {
return new A(b()); // 通过方法调用获取 B 的 Bean
}
@Bean
public B b() {
return new B();
}
}@Configuration类被 CGLIB 创建子类代理@Bean方法被代理拦截:检查容器中是否已有该 Bean,有则返回容器中的单例,无则创建- 保证了
a()中调用b()方法获取的是容器中的单例 Bean
Lite 模式
java
@Configuration(proxyBeanMethods = false) // Lite 模式 — 不代理
// 或 @Component
@Component
public class AppConfig {
@Bean
public A a() {
return new A(b()); // ❌ b() 每次都创建新实例
}
@Bean
public B b() {
return new B();
}
}- 不生成 CGLIB 代理
@Bean方法就是普通方法调用,a()中b()每次返回新实例- 启动更快(无需 CGLIB 字节码生成),但要注意
@Bean方法间调用不再是单例
加 final 的影响
java
@Configuration
public final class AppConfig { // ❌ final 类无法被 CGLIB 继承
// 自动降级为 Lite 模式
// @Bean 方法间调用不再保证单例
}2. @Import 三种方式
java
// 方式 1:导入普通类(注册为 Bean)
@Import(UserService.class)
@Configuration
public class AppConfig { }
// 方式 2:导入 ImportSelector(批量注册)
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 根据条件返回需要注册的类名
return new String[]{
"com.example.service.UserService",
"com.example.service.OrderService"
};
}
}
@Import(MyImportSelector.class)
@Configuration
public class AppConfig { }
// 方式 3:导入 ImportBeanDefinitionRegistrar(精细控制)
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
BeanDefinition def = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.addPropertyValue("name", "custom")
.getBeanDefinition();
registry.registerBeanDefinition("userService", def);
}
}
@Import(MyRegistrar.class)
@Configuration
public class AppConfig { }三种方式对比
| 方式 | 灵活度 | 使用场景 |
|---|---|---|
@Import(普通类) | 低 | 直接注册单个 Bean |
@Import(ImportSelector) | 中 | 根据条件批量注册 |
@Import(ImportBeanDefinitionRegistrar) | 高 | 精细控制 BeanDefinition |
3. @Enable* 注解原理
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(AsyncConfigurationSelector.class) // 核心:导入关键组件
public @interface EnableAsync {
Class<? extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}常见 @Enable* 注解:
| 注解 | 导入的组件 | 功能 |
|---|---|---|
@EnableAsync | AsyncConfigurationSelector → ProxyAsyncConfiguration | 开启异步 |
@EnableScheduling | ScheduledAnnotationBeanPostProcessor | 开启定时任务 |
@EnableAspectJAutoProxy | AspectJAutoProxyRegistrar | 开启 AOP |
@EnableTransactionManagement | TransactionManagementConfigurationSelector | 开启事务 |
@EnableWebMvc | DelegatingWebMvcConfiguration | 开启 MVC 配置 |
@EnableConfigurationProperties | EnableConfigurationPropertiesRegistrar | 开启属性绑定 |
@EnableCaching | CachingConfigurationSelector | 开启缓存 |
4. BeanPostProcessor vs BeanFactoryPostProcessor
| 对比项 | BeanFactoryPostProcessor | BeanPostProcessor |
|---|---|---|
| 操作对象 | BeanDefinition(定义阶段) | Bean 实例(实例化后) |
| 执行时机 | 任何 Bean 实例化之前 | Bean 初始化前后 |
| 典型用途 | 修改 BeanDefinition 属性、占位符替换 | AOP 代理、代理包装 |
| 执行顺序 | refresh() 第 5 步 | refresh() 第 6 步注册,第 11 步调用 |
| 子接口 | BeanDefinitionRegistryPostProcessor | InstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor |
执行时序
5. FactoryBean vs BeanFactory
| FactoryBean<T> | BeanFactory | |
|---|---|---|
| 是什么 | 工厂 Bean,用于创建复杂对象 | IoC 容器顶层接口 |
| 作用 | 自定义 Bean 的创建逻辑 | 管理所有 Bean |
| 获取方式 | &name 获取 FactoryBean,name 获取其产品 | getBean() |
| 典型实现 | SqlSessionFactoryBean、ProxyFactoryBean | DefaultListableBeanFactory |
java
// 自定义 FactoryBean
@Component
public class MyServiceFactory implements FactoryBean<MyService> {
@Override
public MyService getObject() {
// 复杂的创建逻辑
return new MyService("配置参数");
}
@Override
public Class<?> getObjectType() {
return MyService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
// 获取方式
@Autowired
private MyService myService; // 获取 FactoryBean 的产品
@Autowired
private FactoryBean<MyService> factory; // 获取 FactoryBean 本身
// 或在上下文中:ctx.getBean("&myServiceFactory") 获取 FactoryBean 本身