14-Spring-Framework-IoC容器详解

2 阅读10分钟

Spring IoC容器详解

一、知识概述

IoC(Inversion of Control,控制反转)是 Spring 框架的核心思想,它将对象的创建和管理权从应用程序代码转移到了容器中。DI(Dependency Injection,依赖注入)是 IoC 的实现方式,通过容器将依赖关系注入到组件中。

Spring IoC 容器主要负责:

  • Bean 的实例化:创建 Bean 对象
  • 依赖注入:自动装配 Bean 之间的依赖关系
  • 生命周期管理:管理 Bean 的完整生命周期
  • 作用域管理:控制 Bean 的作用范围

理解 IoC 容器的工作原理,是掌握 Spring 框架的基础。

二、知识点详细讲解

2.1 IoC 核心概念

控制反转(IoC)

传统开发中,对象需要主动获取依赖:

// 传统方式
public class UserService {
    private UserDao userDao = new UserDaoImpl(); // 主动创建
}

IoC 模式中,依赖由容器注入:

// IoC 方式
public class UserService {
    private UserDao userDao; // 容器注入
}
依赖注入(DI)方式
  1. 构造器注入:通过构造方法注入依赖
  2. Setter 注入:通过 setter 方法注入依赖
  3. 字段注入:通过 @Autowired 注解直接注入字段(不推荐)

2.2 Bean 的生命周期

实例化 → 属性赋值 → 初始化 → 使用 → 销毁
    │         │         │        │       │
    ↓         ↓         ↓        ↓       ↓
  创建对象   注入依赖   调用初始化  业务方法  调用销毁
生命周期回调
  1. 初始化回调

    • @PostConstruct
    • InitializingBean.afterPropertiesSet()
    • 自定义 init-method
  2. 销毁回调

    • @PreDestroy
    • DisposableBean.destroy()
    • 自定义 destroy-method

2.3 Bean 的作用域

作用域描述适用场景
singleton单例,整个容器中只有一个实例无状态 Bean
prototype每次获取都创建新实例有状态 Bean
request每个 HTTP 请求一个实例Web 应用
session每个 HTTP 会话一个实例Web 应用
application整个 ServletContext 一个实例Web 应用

2.4 自动装配

装配模式
  1. no:不自动装配,显式指定依赖
  2. byName:按名称自动装配
  3. byType:按类型自动装配
  4. constructor:按构造方法自动装配
自动装配注解
  • @Autowired:按类型注入,可配合 @Qualifier 指定名称
  • @Resource:按名称注入(JSR-250)
  • @Inject:按类型注入(JSR-330)

2.5 条件装配

Spring 4 引入了条件化装配:

  • @Conditional:自定义条件
  • @Profile:环境配置
  • @ConditionalOnProperty:属性条件
  • @ConditionalOnClass:类存在条件
  • @ConditionalOnBean:Bean 存在条件

三、代码示例

3.1 依赖注入示例

示例1:构造器注入(推荐)
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

// 接口定义
public interface UserDao {
    User findById(Long id);
}

// 实现类
@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public User findById(Long id) {
        return new User(id, "User-" + id);
    }
}

// 服务类 - 构造器注入
@Service
public class UserService {
    
    private final UserDao userDao;
    private final OrderService orderService;
    
    // 单构造器可省略 @Autowired
    public UserService(UserDao userDao, OrderService orderService) {
        this.userDao = userDao;
        this.orderService = orderService;
    }
    
    public User getUser(Long id) {
        return userDao.findById(id);
    }
}

// 辅助类
public class User {
    private Long id;
    private String name;
    
    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "User{id=" + id + ", name='" + name + "'}";
    }
}

@Service
public class OrderService {
    public String getOrder(Long userId) {
        return "Order for user " + userId;
    }
}
示例2:Setter 注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MessageService {
    
    private MessageSender emailSender;
    private MessageSender smsSender;
    
    // Setter 注入 - 可选依赖
    @Autowired
    public void setEmailSender(MessageSender emailSender) {
        this.emailSender = emailSender;
    }
    
    @Autowired(required = false)  // 可选依赖
    public void setSmsSender(MessageSender smsSender) {
        this.smsSender = smsSender;
    }
    
    public void sendMessage(String message, String type) {
        if ("email".equals(type) && emailSender != null) {
            emailSender.send(message);
        } else if ("sms".equals(type) && smsSender != null) {
            smsSender.send(message);
        }
    }
}

public interface MessageSender {
    void send(String message);
}

@Component
public class EmailSender implements MessageSender {
    @Override
    public void send(String message) {
        System.out.println("发送邮件: " + message);
    }
}
示例3:字段注入(不推荐)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BadPracticeService {
    
    @Autowired  // 字段注入 - 不推荐使用
    private UserDao userDao;
    
    @Autowired
    private List<MessageSender> senders;  // 注入所有匹配类型的 Bean
    
    public User getUser(Long id) {
        return userDao.findById(id);
    }
}

// 问题:
// 1. 无法在容器外使用
// 2. 无法设置可选依赖
// 3. 难以单元测试
// 4. 违反单一职责原则

3.2 Bean 生命周期示例

import org.springframework.beans.factory.*;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

@Component
public class LifecycleBean implements InitializingBean, DisposableBean, 
                                      BeanNameAware, BeanFactoryAware {
    
    private String beanName;
    private BeanFactory beanFactory;
    
    // 1. 实例化(构造方法)
    public LifecycleBean() {
        System.out.println("1. 构造方法执行");
    }
    
    // 2. BeanNameAware 回调
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("2. BeanNameAware: " + name);
    }
    
    // 3. BeanFactoryAware 回调
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
        System.out.println("3. BeanFactoryAware 设置完成");
    }
    
    // 4. 属性注入(由容器完成)
    
    // 5. @PostConstruct 初始化
    @PostConstruct
    public void postConstruct() {
        System.out.println("5. @PostConstruct 初始化");
    }
    
    // 6. InitializingBean 回调
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("6. InitializingBean.afterPropertiesSet()");
    }
    
    // 7. 自定义 init-method
    public void customInit() {
        System.out.println("7. 自定义 init-method");
    }
    
    // 业务方法
    public void doSomething() {
        System.out.println("Bean 正常工作...");
    }
    
    // 8. @PreDestroy 销毁
    @PreDestroy
    public void preDestroy() {
        System.out.println("8. @PreDestroy 销毁");
    }
    
    // 9. DisposableBean 回调
    @Override
    public void destroy() throws Exception {
        System.out.println("9. DisposableBean.destroy()");
    }
    
    // 10. 自定义 destroy-method
    public void customDestroy() {
        System.out.println("10. 自定义 destroy-method");
    }
}

// 配置类
@Configuration
@ComponentScan
public class LifecycleConfig {
    
    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public LifecycleBean lifecycleBean() {
        return new LifecycleBean();
    }
}

// 测试
public class LifecycleDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(LifecycleConfig.class);
        
        LifecycleBean bean = context.getBean(LifecycleBean.class);
        bean.doSomething();
        
        context.close();
    }
}

// 输出:
// 1. 构造方法执行
// 2. BeanNameAware: lifecycleBean
// 3. BeanFactoryAware 设置完成
// 5. @PostConstruct 初始化
// 6. InitializingBean.afterPropertiesSet()
// 7. 自定义 init-method
// Bean 正常工作...
// 8. @PreDestroy 销毁
// 9. DisposableBean.destroy()
// 10. 自定义 destroy-method

3.3 Bean 作用域示例

import org.springframework.context.annotation.*;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.web.context.WebApplicationContext;

// 单例 Bean
@Component
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class SingletonBean {
    private int counter = 0;
    
    public int increment() {
        return ++counter;
    }
    
    public int getCounter() {
        return counter;
    }
}

// 原型 Bean
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeBean {
    private String id = java.util.UUID.randomUUID().toString().substring(0, 8);
    
    public String getId() {
        return id;
    }
}

// Request 作用域(Web 环境)
@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
    private String requestId = java.util.UUID.randomUUID().toString();
    
    public String getRequestId() {
        return requestId;
    }
}

// Session 作用域(Web 环境)
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, 
       proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopedBean {
    private String sessionId;
    private java.util.Date loginTime;
    
    public void init(String sessionId) {
        this.sessionId = sessionId;
        this.loginTime = new java.util.Date();
    }
    
    public String getSessionInfo() {
        return "Session: " + sessionId + ", Login: " + loginTime;
    }
}

// 测试
@Configuration
@ComponentScan
public class ScopeDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(ScopeDemo.class);
        
        // 单例测试
        SingletonBean singleton1 = context.getBean(SingletonBean.class);
        SingletonBean singleton2 = context.getBean(SingletonBean.class);
        
        System.out.println("单例测试:");
        System.out.println("singleton1.increment() = " + singleton1.increment());
        System.out.println("singleton2.increment() = " + singleton2.increment());
        System.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));
        
        // 原型测试
        System.out.println("\n原型测试:");
        PrototypeBean prototype1 = context.getBean(PrototypeBean.class);
        PrototypeBean prototype2 = context.getBean(PrototypeBean.class);
        
        System.out.println("prototype1.id = " + prototype1.getId());
        System.out.println("prototype2.id = " + prototype2.getId());
        System.out.println("prototype1 == prototype2: " + (prototype1 == prototype2));
        
        context.close();
    }
}

// 输出:
// 单例测试:
// singleton1.increment() = 1
// singleton2.increment() = 2
// singleton1 == singleton2: true
//
// 原型测试:
// prototype1.id = a1b2c3d4
// prototype2.id = e5f6g7h8
// prototype1 == prototype2: false

3.4 自动装配示例

import org.springframework.beans.factory.annotation.*;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.*;
import java.util.*;

// 多个实现类的自动装配

public interface PaymentProcessor {
    void process(double amount);
}

@Component
@Qualifier("alipay")
public class AlipayProcessor implements PaymentProcessor {
    @Override
    public void process(double amount) {
        System.out.println("支付宝支付: ¥" + amount);
    }
}

@Component
@Qualifier("wechat")
public class WechatPayProcessor implements PaymentProcessor {
    @Override
    public void process(double amount) {
        System.out.println("微信支付: ¥" + amount);
    }
}

@Component
@Primary  // 默认选择
public class DefaultPayProcessor implements PaymentProcessor {
    @Override
    public void process(double amount) {
        System.out.println("默认支付方式: ¥" + amount);
    }
}

// 服务类 - 自动装配
@Service
public class PaymentService {
    
    // 使用 @Primary 的 Bean
    private final PaymentProcessor defaultProcessor;
    
    // 使用 @Qualifier 指定 Bean
    private final PaymentProcessor alipayProcessor;
    
    // 注入所有匹配类型的 Bean
    private final Map<String, PaymentProcessor> processorMap;
    
    public PaymentService(
            @Autowired PaymentProcessor defaultProcessor,
            @Autowired @Qualifier("alipay") PaymentProcessor alipayProcessor,
            @Autowired Map<String, PaymentProcessor> processorMap) {
        this.defaultProcessor = defaultProcessor;
        this.alipayProcessor = alipayProcessor;
        this.processorMap = processorMap;
    }
    
    public void payDefault(double amount) {
        defaultProcessor.process(amount);
    }
    
    public void payByAlipay(double amount) {
        alipayProcessor.process(amount);
    }
    
    public void payByType(String type, double amount) {
        PaymentProcessor processor = processorMap.get(type + "PayProcessor");
        if (processor != null) {
            processor.process(amount);
        } else {
            System.out.println("不支持的支付方式: " + type);
        }
    }
}

@Configuration
@ComponentScan
public class AutowireDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AutowireDemo.class);
        
        PaymentService service = context.getBean(PaymentService.class);
        
        service.payDefault(100);
        service.payByAlipay(200);
        service.payByType("wechat", 300);
        
        context.close();
    }
}

// 输出:
// 默认支付方式: ¥100.0
// 支付宝支付: ¥200.0
// 微信支付: ¥300.0

3.5 条件装配示例

import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.boot.autoconfigure.condition.*;

// 自定义条件注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
    String name();
    String value();
}

// 自定义条件
class OnSystemPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(
            ConditionalOnSystemProperty.class.getName());
        String name = (String) attributes.get("name");
        String value = (String) attributes.get("value");
        
        String systemValue = System.getProperty(name);
        return value.equals(systemValue);
    }
}

// 条件装配的 Bean
@Configuration
public class ConditionalConfig {
    
    @Bean
    @ConditionalOnSystemProperty(name = "env", value = "dev")
    public DataSource devDataSource() {
        return new DataSource("dev-db", "dev-user");
    }
    
    @Bean
    @ConditionalOnSystemProperty(name = "env", value = "prod")
    public DataSource prodDataSource() {
        return new DataSource("prod-db", "prod-user");
    }
    
    @Bean
    @ConditionalOnClass(name = "java.sql.Driver")
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    
    @Bean
    @ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
    public FeatureService featureService() {
        return new FeatureService();
    }
    
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource defaultDataSource() {
        return new DataSource("default-db", "default-user");
    }
}

// 数据源模拟类
public class DataSource {
    private final String url;
    private final String username;
    
    public DataSource(String url, String username) {
        this.url = url;
        this.username = username;
    }
    
    @Override
    public String toString() {
        return "DataSource{url='" + url + "', username='" + username + "'}";
    }
}

public class JdbcTemplate {
    private final DataSource dataSource;
    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}

public class FeatureService {
    public void doSomething() {
        System.out.println("Feature enabled!");
    }
}

// Profile 示例
@Configuration
public class ProfileConfig {
    
    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return new DataSource("jdbc:mysql://localhost:3306/dev", "dev");
    }
    
    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return new DataSource("jdbc:mysql://prod-server:3306/prod", "prod");
    }
    
    @Bean
    @Profile("test")
    public DataSource testDataSource() {
        return new DataSource("jdbc:h2:mem:testdb", "sa");
    }
}

// 测试
public class ConditionalDemo {
    public static void main(String[] args) {
        // 设置环境
        System.setProperty("env", "dev");
        System.setProperty("feature.enabled", "true");
        
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(ConditionalConfig.class);
        
        DataSource dataSource = context.getBean(DataSource.class);
        System.out.println("DataSource: " + dataSource);
        
        if (context.containsBean("featureService")) {
            FeatureService feature = context.getBean(FeatureService.class);
            feature.doSomething();
        }
        
        context.close();
    }
}

3.6 循环依赖解决

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

// 循环依赖示例
@Component
public class ServiceA {
    private final ServiceB serviceB;
    
    @Autowired
    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
    
    public void doSomething() {
        System.out.println("ServiceA working");
    }
}

@Component
public class ServiceB {
    private final ServiceA serviceA;
    
    @Autowired
    public ServiceB(ServiceA serviceA) {
        this.serviceA = serviceA;
    }
    
    public void doSomething() {
        System.out.println("ServiceB working");
    }
}

// 解决方案1:使用 @Lazy
@Component
public class ServiceA2 {
    private final ServiceB2 serviceB;
    
    @Autowired
    public ServiceA2(@Lazy ServiceB2 serviceB) {
        this.serviceB = serviceB;
    }
}

@Component
public class ServiceB2 {
    private final ServiceA2 serviceA;
    
    @Autowired
    public ServiceB2(ServiceA2 serviceA) {
        this.serviceA = serviceA;
    }
}

// 解决方案2:使用 Setter 注入
@Component
public class ServiceA3 {
    private ServiceB3 serviceB;
    
    @Autowired
    public void setServiceB(ServiceB3 serviceB) {
        this.serviceB = serviceB;
    }
}

@Component
public class ServiceB3 {
    private ServiceA3 serviceA;
    
    @Autowired
    public void setServiceA(ServiceA3 serviceA) {
        this.serviceA = serviceA;
    }
}

// 解决方案3:重构设计,避免循环依赖
public interface CommonService {
    void doSomething();
}

@Component
public class ServiceA4 {
    private final CommonService commonService;
    
    public ServiceA4(CommonService commonService) {
        this.commonService = commonService;
    }
}

@Component
public class ServiceB4 implements CommonService {
    @Override
    public void doSomething() {
        System.out.println("ServiceB working");
    }
}

// 测试
@Configuration
@ComponentScan
public class CircularDependencyDemo {
    public static void main(String[] args) {
        try {
            AnnotationConfigApplicationContext context = 
                new AnnotationConfigApplicationContext(CircularDependencyDemo.class);
            
            System.out.println("容器启动成功");
            
            ServiceA2 serviceA = context.getBean(ServiceA2.class);
            serviceA.doSomething();
            
            context.close();
        } catch (Exception e) {
            System.out.println("循环依赖异常: " + e.getMessage());
        }
    }
}

四、实战应用场景

4.1 分层架构的依赖注入

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.context.annotation.*;
import java.util.*;

// 实体类
public class User {
    private Long id;
    private String username;
    private String email;
    
    // 构造器、getter、setter
    public User() {}
    
    public User(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }
    
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    @Override
    public String toString() {
        return "User{id=" + id + ", username='" + username + "', email='" + email + "'}";
    }
}

// Repository 层
public interface UserRepository {
    User findById(Long id);
    User save(User user);
    List<User> findAll();
}

@Repository
public class UserRepositoryImpl implements UserRepository {
    
    private final Map<Long, User> storage = new HashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);
    
    @Override
    public User findById(Long id) {
        return storage.get(id);
    }
    
    @Override
    public User save(User user) {
        if (user.getId() == null) {
            user.setId(idGenerator.getAndIncrement());
        }
        storage.put(user.getId(), user);
        return user;
    }
    
    @Override
    public List<User> findAll() {
        return new ArrayList<>(storage.values());
    }
}

// Service 层
public interface UserService {
    User getUser(Long id);
    User createUser(String username, String email);
    List<User> getAllUsers();
}

@Service
public class UserServiceImpl implements UserService {
    
    private final UserRepository userRepository;
    private final NotificationService notificationService;
    
    public UserServiceImpl(UserRepository userRepository, 
                           NotificationService notificationService) {
        this.userRepository = userRepository;
        this.notificationService = notificationService;
    }
    
    @Override
    public User getUser(Long id) {
        return userRepository.findById(id);
    }
    
    @Override
    public User createUser(String username, String email) {
        User user = new User(null, username, email);
        User saved = userRepository.save(user);
        notificationService.notifyUserCreated(saved);
        return saved;
    }
    
    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

// 通知服务
public interface NotificationService {
    void notifyUserCreated(User user);
}

@Service
public class EmailNotificationService implements NotificationService {
    
    @Override
    public void notifyUserCreated(User user) {
        System.out.println("发送邮件通知: 用户 " + user.getUsername() + " 已创建");
    }
}

// 配置类
@Configuration
@ComponentScan
public class LayeredArchitectureDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(LayeredArchitectureDemo.class);
        
        UserService userService = context.getBean(UserService.class);
        
        // 创建用户
        User user1 = userService.createUser("张三", "zhangsan@example.com");
        User user2 = userService.createUser("李四", "lisi@example.com");
        
        // 查询用户
        System.out.println("\n所有用户:");
        userService.getAllUsers().forEach(System.out::println);
        
        context.close();
    }
}

4.2 多数据源配置

import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.HashMap;

// 数据源配置
@Configuration
public class MultiDataSourceConfig {
    
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    // 简化示例
    @Bean
    @Primary
    public DataSource primaryDataSourceSimple() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setUrl("jdbc:mysql://localhost:3306/primary_db");
        ds.setUsername("root");
        ds.setPassword("password");
        return ds;
    }
    
    @Bean
    public DataSource secondaryDataSourceSimple() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setUrl("jdbc:mysql://localhost:3306/secondary_db");
        ds.setUsername("root");
        ds.setPassword("password");
        return ds;
    }
}

// 动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
    
    private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
    
    public static void setDataSource(String name) {
        CONTEXT.set(name);
    }
    
    public static void clearDataSource() {
        CONTEXT.remove();
    }
    
    @Override
    protected Object determineCurrentLookupKey() {
        return CONTEXT.get();
    }
}

// 动态数据源配置
@Configuration
public class DynamicDataSourceConfig {
    
    @Bean
    public DataSource dynamicDataSource(
            DataSource primaryDataSource, 
            DataSource secondaryDataSource) {
        
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("primary", primaryDataSource);
        targetDataSources.put("secondary", secondaryDataSource);
        
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);
        
        return dynamicDataSource;
    }
}

// 数据源切换注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value() default "primary";
}

// 切面实现
@Aspect
@Component
public class DataSourceAspect {
    
    @Around("@annotation(dataSource)")
    public Object around(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
        try {
            DynamicDataSource.setDataSource(dataSource.value());
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
}

// 使用示例
@Service
public class OrderService {
    
    @DataSource("primary")
    public void saveOrder(Order order) {
        // 使用主数据源
    }
    
    @DataSource("secondary")
    public List<Order> queryOrders() {
        // 使用从数据源
        return new ArrayList<>();
    }
}

五、IoC 容器实现原理

5.1 容器启动流程

1. Resource 定位 → 找到配置文件
2. BeanDefinition 加载 → 解析配置,生成 BeanDefinition
3. BeanDefinition 注册 → 注册到 BeanDefinitionRegistry
4. Bean 实例化 → 创建 Bean 实例
5. 依赖注入 → 注入依赖关系
6. 生命周期回调 → 执行初始化回调

5.2 BeanFactory vs ApplicationContext

特性BeanFactoryApplicationContext
实例化时机延迟实例化启动时实例化
国际化不支持支持
事件发布不支持支持
AOP 集成需手动配置自动支持
资源访问不支持支持

5.3 BeanPostProcessor 扩展点

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        System.out.println("初始化前处理: " + beanName);
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
            throws BeansException {
        System.out.println("初始化后处理: " + beanName);
        
        // 可以返回代理对象
        if (bean instanceof UserService) {
            return createProxy(bean);
        }
        
        return bean;
    }
    
    private Object createProxy(Object target) {
        // 创建代理逻辑
        return java.lang.reflect.Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                System.out.println("Before: " + method.getName());
                Object result = method.invoke(target, args);
                System.out.println("After: " + method.getName());
                return result;
            }
        );
    }
}

六、总结与最佳实践

最佳实践

  1. 依赖注入方式选择

    • 构造器注入:强制依赖
    • Setter 注入:可选依赖
    • 避免字段注入
  2. 作用域选择

    • 无状态 Bean:singleton(默认)
    • 有状态 Bean:prototype
    • Web 请求相关:request/session
  3. 循环依赖避免

    • 重构设计,消除循环依赖
    • 使用 @Lazy 延迟加载
    • 使用 Setter 注入
  4. 配置方式选择

    • 简单配置:@Component + @ComponentScan
    • 复杂配置:@Configuration + @Bean
    • 条件配置:@Conditional 系列

常见问题

  1. NoSuchBeanDefinitionException

    • 检查组件扫描配置
    • 检查 Bean 名称匹配
  2. NoUniqueBeanDefinitionException

    • 使用 @Primary 或 @Qualifier
  3. BeanCreationException

    • 检查构造方法参数
    • 检查循环依赖
  4. BeanCurrentlyInCreationException

    • 存在循环依赖
    • 使用 @Lazy 解决

Spring IoC 容器是 Spring 框架的核心,理解其工作原理对于正确使用 Spring 至关重要。通过依赖注入,可以实现松耦合、易测试的代码结构,提高代码的可维护性和可扩展性。