Skip to content

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* 注解:

注解导入的组件功能
@EnableAsyncAsyncConfigurationSelectorProxyAsyncConfiguration开启异步
@EnableSchedulingScheduledAnnotationBeanPostProcessor开启定时任务
@EnableAspectJAutoProxyAspectJAutoProxyRegistrar开启 AOP
@EnableTransactionManagementTransactionManagementConfigurationSelector开启事务
@EnableWebMvcDelegatingWebMvcConfiguration开启 MVC 配置
@EnableConfigurationPropertiesEnableConfigurationPropertiesRegistrar开启属性绑定
@EnableCachingCachingConfigurationSelector开启缓存

4. BeanPostProcessor vs BeanFactoryPostProcessor

对比项BeanFactoryPostProcessorBeanPostProcessor
操作对象BeanDefinition(定义阶段)Bean 实例(实例化后)
执行时机任何 Bean 实例化之前Bean 初始化前后
典型用途修改 BeanDefinition 属性、占位符替换AOP 代理、代理包装
执行顺序refresh() 第 5 步refresh() 第 6 步注册,第 11 步调用
子接口BeanDefinitionRegistryPostProcessorInstantiationAwareBeanPostProcessorDestructionAwareBeanPostProcessor

执行时序


5. FactoryBean vs BeanFactory

FactoryBean<T>BeanFactory
是什么工厂 Bean,用于创建复杂对象IoC 容器顶层接口
作用自定义 Bean 的创建逻辑管理所有 Bean
获取方式&name 获取 FactoryBean,name 获取其产品getBean()
典型实现SqlSessionFactoryBeanProxyFactoryBeanDefaultListableBeanFactory
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 本身

Knowledge4J — Java 知识库