第三节 IoC容器核心机制

117 阅读3分钟

1.3 IoC容器核心机制

1.3.1 Bean生命周期全流程解析(深度源码级)

完整生命周期流程图

graph TD
    A[实例化Bean] --> B[属性填充]
    B --> C[BeanNameAware.setBeanName]
    C --> D[BeanFactoryAware.setBeanFactory]
    D --> E[ApplicationContextAware.setApplicationContext]
    E --> F[BeanPostProcessor.postProcessBeforeInitialization]
    F --> G["@PostConstruct"]
    G --> H[InitializingBean.afterPropertiesSet]
    H --> I[自定义init-method]
    I --> J[BeanPostProcessor.postProcessAfterInitialization]
    J --> K[Bean就绪]
    K --> L[容器关闭]
    L --> M["@PreDestroy"]
    M --> N[DisposableBean.destroy]
    N --> O[自定义destroy-method]

关键阶段代码演示

public class LifecycleBean implements 
    BeanNameAware, BeanFactoryAware, 
    ApplicationContextAware, InitializingBean, DisposableBean {

    private String beanName;
    
    // 1. Aware接口注入
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("BeanNameAware: "+name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println("BeanFactoryAware注入完成");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println("ApplicationContextAware注入完成");
    }

    // 2. 初始化回调
    @PostConstruct
    public void customInit() {
        System.out.println("@PostConstruct方法执行");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean.afterPropertiesSet执行");
    }

    public void xmlInit() {
        System.out.println("XML定义的init-method执行");
    }

    // 3. 销毁回调
    @PreDestroy
    public void customDestroy() {
        System.out.println("@PreDestroy方法执行");
    }

    @Override
    public void destroy() {
        System.out.println("DisposableBean.destroy执行");
    }

    public void xmlDestroy() {
        System.out.println("XML定义的destroy-method执行");
    }
}

// 配置类
@Configuration
public class LifecycleConfig {
    @Bean(initMethod = "xmlInit", destroyMethod = "xmlDestroy")
    public LifecycleBean lifecycleBean() {
        return new LifecycleBean();
    }
    
    @Bean
    public static BeanPostProcessor customProcessor() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) {
                System.out.println("BeanPostProcessor前置处理: "+beanName);
                return bean;
            }
            
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) {
                System.out.println("BeanPostProcessor后置处理: "+beanName);
                return bean;
            }
        };
    }
}

控制台输出顺序

BeanNameAware: lifecycleBean
BeanFactoryAware注入完成
ApplicationContextAware注入完成
BeanPostProcessor前置处理: lifecycleBean
@PostConstruct方法执行
InitializingBean.afterPropertiesSet执行
XML定义的init-method执行
BeanPostProcessor后置处理: lifecycleBean
... [容器运行中]
@PreDestroy方法执行
DisposableBean.destroy执行
XML定义的destroy-method执行

1.3.2 依赖注入的六种实现方式(企业级最佳实践)

注入方式对照表

注入方式实现形式适用场景注意事项
构造器注入@Autowired构造函数强制依赖、不可变对象解决循环依赖的首选方式
Setter注入@Autowired set方法可选依赖、需要重新配置避免在并发场景下修改
字段注入@Autowired字段快速开发、简单场景不利于单元测试
方法注入@Bean工厂方法复杂对象创建逻辑需配合@Configuration使用
接口回调注入ApplicationContextAware获取容器基础设施增加代码耦合度
查找方法注入@Lookup注解原型Bean注入单例Bean需要CGLIB代理

构造器注入最佳实践

@Service
public class OrderService {
    private final PaymentService paymentService;
    private final InventoryService inventoryService;

    // 显式构造器注入
    @Autowired
    public OrderService(PaymentService paymentService, 
                       InventoryService inventoryService) {
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }
}

// 解决循环依赖方案
@Configuration
public class CircularDependencyConfig {
    @Bean
    @Lazy
    public ServiceA serviceA(ServiceB serviceB) {
        return new ServiceA(serviceB);
    }

    @Bean
    @Lazy
    public ServiceB serviceB(ServiceA serviceA) {
        return new ServiceB(serviceA);
    }
}

查找方法注入实战

@Component
@Scope("prototype")
public class PrototypeBean {
    private static int count = 0;
    private final int id;

    public PrototypeBean() {
        this.id = ++count;
    }

    public void printId() {
        System.out.println("PrototypeBean ID: " + id);
    }
}

@Component
public class SingletonBean {
    // 每次调用获得新的原型Bean
    @Lookup
    public PrototypeBean getPrototypeBean() {
        return null; // 实际由CGLIB实现
    }

    public void execute() {
        PrototypeBean bean = getPrototypeBean();
        bean.printId();
    }
}

1.3.3 自动装配的智能决策机制

自动装配冲突解决策略

graph TD
    A[发现多个候选Bean] --> B{"是否有@Primary标记?"}
    B -->|是| C["选择@Primary的Bean"]
    B -->|否| D{"是否有@Qualifier指定?"}
    D -->|是| E[按限定符选择]
    D -->|否| F{是否开启宽松模式?}
    F -->|是| G[按名称匹配]
    F -->|否| H[抛出NoUniqueBeanDefinitionException]

企业级配置案例

// 主数据源配置
@Configuration
public class PrimaryDataSourceConfig {
    @Bean
    @Primary
    public DataSource mainDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://master:3306/core")
            .username("admin")
            .password("secure123")
            .build();
    }

    @Bean
    public DataSource reportDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://replica:3306/report")
            .username("readonly")
            .password("readonly123")
            .build();
    }
}

// 业务服务层
@Service
public class ReportService {
    private final DataSource dataSource;

    // 明确指定非主数据源
    public ReportService(@Qualifier("reportDataSource") DataSource dataSource) {
        this.dataSource = dataSource;
    }
}

自动装配异常处理方案

// 1. 使用Optional避免依赖不存在
@Autowired
public void setOptionalDependency(Optional<SomeService> service) {
    service.ifPresent(s -> this.service = s);
}

// 2. 自定义缺失Bean处理
@Bean
@ConditionalOnMissingBean
public DefaultCacheManager defaultCache() {
    return new DefaultCacheManager();
}

// 3. 集合类型安全注入
@Autowired
public void setStrategies(List<BusinessStrategy> strategies) {
    this.strategyMap = strategies.stream()
        .collect(Collectors.toMap(
            s -> s.getClass().getSimpleName(), 
            Function.identity()
        ));
}

1.3.4 条件化Bean配置实战

多环境数据源切换方案

// 条件判断类
public class EnvCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        String env = context.getEnvironment()
                          .getProperty("app.env", "dev");
        return "prod".equals(env);
    }
}

// 生产环境配置
@Configuration
@Conditional(EnvCondition.class)
public class ProdDataSourceConfig {
    @Bean
    public DataSource prodDataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://prod-db:3306/core");
        config.setUsername("prod_user");
        config.setPassword(System.getenv("DB_PROD_PASS"));
        config.setConnectionTimeout(3000);
        return new HikariDataSource(config);
    }
}

// 开发环境配置
@Profile("dev")
@Configuration
public class DevDataSourceConfig {
    @Bean
    public DataSource devDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript("classpath:schema.sql")
            .build();
    }
}

条件注解组合使用

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnCloudPlatformCondition.class)
@Conditional(OnKubernetesEnvCondition.class)
public @interface ConditionalOnCloudKubernetes {}

// 云原生环境专属配置
@Configuration
@ConditionalOnCloudKubernetes
public class CloudNativeConfig {
    @Bean
    public ServiceDiscovery serviceDiscovery() {
        return new KubernetesServiceDiscovery();
    }
}