前言:某次线上事故让我重新审视了Spring Bean的管理。当时由于错误使用原型作用域的Bean导致内存溢出,最终通过调整Bean的创建方式解决了问题。这让我深刻意识到:真正掌握Spring IOC的关键在于理解Bean的创建方式及其适用场景。
一、IOC容器启动实战
在Spring Boot中,容器启动方式早已简化:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
传统XML方式仍值得了解:
<!-- 通过ClassPathXmlApplicationContext启动 -->
<beans>
<context:component-scan base-package="com.example"/>
</beans>
二、Bean创建九大招式详解
- XML显式配置(适合遗留系统维护)
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="${db.url}"/>
<property name="username" value="${db.user}"/>
</bean>
- @Component注解(业务层首选)
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
}
- @Bean方法注册(第三方库集成利器)
@Configuration
public class CacheConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
}
- 静态工厂方法(连接池常用)
public class ConnectionFactory {
public static DataSource createDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost/test");
return new HikariDataSource(config);
}
}
// XML配置
<bean id="dataSource" class="com.example.ConnectionFactory"
factory-method="createDataSource"/>
- 实例工厂方法(工厂模式实现)
public class PaymentStrategyFactory {
public PaymentStrategy createAlipayStrategy() {
return new AlipayStrategy();
}
}
// XML配置
<bean id="strategyFactory" class="com.example.PaymentStrategyFactory"/>
<bean id="alipayStrategy" factory-bean="strategyFactory"
factory-method="createAlipayStrategy"/>
- FactoryBean接口(复杂对象创建)
public class ClusterRedisFactoryBean implements FactoryBean<RedisCluster> {
@Override
public RedisCluster getObject() throws Exception {
// 构建Redis集群连接
return new RedisCluster(nodes);
}
}
- ImportSelector动态注册(条件化加载)
public class FeatureToggleSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
return isFeatureEnabled() ?
new String[]{FeatureConfig.class.getName()} : new String[0];
}
}
- BeanDefinition注册(底层扩展)
public class CustomBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(SecurityFilter.class);
registry.registerBeanDefinition("securityFilter", definition);
}
}
- SPI扩展(高级插件化)
在META-INF/spring.factories中:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.plugin.SmsAutoConfiguration
三、实战避坑指南
- 循环依赖解决方案
- 使用@Lazy延迟加载
- 改用setter注入
- 调整Bean初始化顺序
- 作用域选择策略
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.TARGET_CLASS)
- 生命周期管理示例
@Bean(initMethod = "init", destroyMethod = "cleanup")
public class DatabasePool {
public void init() { /* 连接池预热 */ }
public void cleanup() { /* 释放连接 */ }
}
总结:在微服务架构下,推荐采用@Bean+@Configuration组合方式管理基础组件,业务Bean使用@Component注解扫描。对于需要动态决策的Bean,FactoryBean和ImportSelector是更好的选择。理解每种方式的实现原理,才能在面对性能优化、组件扩展等场景时游刃有余。