Spring IOC详解:从原理到实战
前言
Spring框架的核心是IoC(Inversion of Control,控制反转)容器,它是Spring框架的基石。理解IoC容器的工作原理和使用方式,对于深入掌握Spring框架至关重要。本文将从IoC的基本概念出发,结合源码分析和实战案例,全面解析Spring IoC容器的核心知识点。
一、什么是IoC
1.1 控制反转的概念
IoC(Inversion of Control)控制反转,是一种设计思想。传统的程序设计中,对象的创建和依赖关系的管理都是由程序代码直接控制的。而在IoC中,这些控制权被"反转"给了容器。
传统方式 vs IoC方式
┌─────────────────────────────────────────────┐
│ 传统方式: │
│ ┌──────────┐ new ┌──────────┐ │
│ │ UserService│ ─────────> │ UserDao │ │
│ └──────────┘ └──────────┘ │
│ 对象主动创建依赖 │
├─────────────────────────────────────────────┤
│ IoC方式: │
│ ┌──────────┐ ┌──────────┐ │
│ │UserService│ │ UserDao │ │
│ └─────┬────┘ └─────┬────┘ │
│ │ │ │
│ └───────┐ ┌───────┘ │
│ ▼ ▼ │
│ ┌─────────────┐ │
│ │ IoC Container│ │
│ └─────────────┘ │
│ 容器负责创建对象和注入依赖 │
└─────────────────────────────────────────────┘
1.2 为什么需要IoC
/**
* 传统方式的问题
*/
public class UserServiceOld {
// 紧耦合:直接依赖具体实现
private UserDao userDao = new UserDaoImpl();
public User findUser(Long id) {
return userDao.findById(id);
}
}
// 问题:
// 1. 紧耦合:UserService直接依赖UserDaoImpl
// 2. 难以测试:无法mock UserDao
// 3. 难以扩展:要换实现必须修改代码
/**
* IoC方式的优势
*/
public class UserService {
// 依赖抽象,由外部注入
private UserDao userDao;
// 构造器注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public User findUser(Long id) {
return userDao.findById(id);
}
}
// 优势:
// 1. 松耦合:依赖抽象而非具体实现
// 2. 易于测试:可以注入Mock对象
// 3. 易于扩展:更换实现无需修改代码
1.3 DI(依赖注入)
DI(Dependency Injection)依赖注入,是IoC的一种实现方式。它通过外部注入依赖对象,而不是在对象内部创建。
IoC和DI的关系
┌─────────────────────────────────┐
│ IoC (控制反转) │
│ - 设计思想/原则 │
│ - 将控制权交给容器 │
│ │
│ ┌─────────────────────────┐ │
│ │ DI (依赖注入) │ │
│ │ - IoC的具体实现方式 │ │
│ │ - 构造器注入 │ │
│ │ - Setter注入 │ │
│ │ - 字段注入 │ │
│ └─────────────────────────┘ │
└─────────────────────────────────┘
二、Spring IoC容器
2.1 BeanFactory与ApplicationContext
Spring提供了两种IoC容器:BeanFactory和ApplicationContext。
IoC容器层次结构
BeanFactory
↑
│
ApplicationContext
↑
┌────────────┼────────────┐
│ │ │
ClassPathXml FileSystemXml AnnotationConfig
ApplicationContext ApplicationContext ApplicationContext
/**
* BeanFactory - 基础容器
*/
public class BeanFactoryDemo {
public static void main(String[] args) {
// 创建资源对象
Resource resource = new ClassPathResource("beans.xml");
// 创建BeanFactory
BeanFactory factory = new XmlBeanFactory(resource);
// 获取Bean(延迟加载)
UserService userService = (UserService) factory.getBean("userService");
}
}
/**
* ApplicationContext - 高级容器
*/
public class ApplicationContextDemo {
public static void main(String[] args) {
// 创建ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 获取Bean(预加载)
UserService userService = context.getBean("userService", UserService.class);
// ApplicationContext提供更多功能
String[] beanNames = context.getBeanDefinitionNames();
for (String name : beanNames) {
System.out.println(name);
}
}
}
BeanFactory vs ApplicationContext:
┌───────────────────┬─────────────────┬────────────────────┐
│ 特性 │ BeanFactory │ ApplicationContext │
├───────────────────┼─────────────────┼────────────────────┤
│ Bean加载 │ 延迟加载 │ 立即加载 │
│ 国际化支持 │ 不支持 │ 支持 │
│ 事件发布 │ 不支持 │ 支持 │
│ AOP支持 │ 需手动配置 │ 自动支持 │
│ 资源访问 │ 较弱 │ 强大 │
│ 使用场景 │ 资源受限环境 │ 企业级应用 │
└───────────────────┴─────────────────┴────────────────────┘
2.2 Bean的配置方式
2.2.1 XML配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义Bean -->
<bean id="userDao" class="com.example.dao.impl.UserDaoImpl"/>
<!-- 构造器注入 -->
<bean id="userService" class="com.example.service.UserService">
<constructor-arg ref="userDao"/>
</bean>
<!-- Setter注入 -->
<bean id="orderService" class="com.example.service.OrderService">
<property name="orderDao" ref="orderDao"/>
<property name="timeout" value="30"/>
</bean>
<!-- 集合注入 -->
<bean id="emailService" class="com.example.service.EmailService">
<property name="receivers">
<list>
<value>admin@example.com</value>
<value>support@example.com</value>
</list>
</property>
</bean>
</beans>
2.2.2 注解配置
/**
* 配置类
*/
@Configuration
public class AppConfig {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
@Bean
public UserService userService() {
return new UserService(userDao());
}
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/demo");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
}
/**
* 使用配置类
*/
public class AnnotationConfigDemo {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
}
}
2.2.3 组件扫描
/**
* 启用组件扫描
*/
@Configuration
@ComponentScan(basePackages = "com.example")
public class ScanConfig {
}
/**
* DAO层
*/
@Repository
public class UserDaoImpl implements UserDao {
@Override
public User findById(Long id) {
System.out.println("查询用户: " + id);
return new User(id, "User" + id);
}
}
/**
* Service层
*/
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User getUser(Long id) {
return userDao.findById(id);
}
}
/**
* Controller层
*/
@Controller
public class UserController {
@Autowired
private UserService userService;
public void handleRequest(Long userId) {
User user = userService.getUser(userId);
System.out.println("处理用户请求: " + user);
}
}
三、依赖注入方式
3.1 构造器注入
/**
* 构造器注入(推荐方式)
*/
@Service
public class OrderService {
private final OrderDao orderDao;
private final PaymentService paymentService;
// Spring 4.3+,单个构造器可以省略@Autowired
@Autowired
public OrderService(OrderDao orderDao, PaymentService paymentService) {
this.orderDao = orderDao;
this.paymentService = paymentService;
}
public void createOrder(Order order) {
orderDao.save(order);
paymentService.processPayment(order.getId());
}
}
// 优点:
// 1. 保证依赖不可变(final)
// 2. 依赖明确,易于测试
// 3. 防止空指针异常
// 4. 支持循环依赖检测
3.2 Setter注入
/**
* Setter注入
*/
@Service
public class EmailService {
private TemplateEngine templateEngine;
private MailSender mailSender;
@Autowired
public void setTemplateEngine(TemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
@Autowired
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void sendEmail(String to, String subject, String content) {
String body = templateEngine.process(content);
mailSender.send(to, subject, body);
}
}
// 优点:
// 1. 可选依赖
// 2. 可以在对象创建后修改依赖
// 缺点:
// 1. 依赖可变
// 2. 可能出现空指针
3.3 字段注入
/**
* 字段注入(不推荐,但最常用)
*/
@Service
public class ProductService {
@Autowired
private ProductDao productDao;
@Autowired
private InventoryService inventoryService;
public Product getProduct(Long id) {
Product product = productDao.findById(id);
product.setStock(inventoryService.getStock(id));
return product;
}
}
// 优点:
// 1. 代码简洁
// 缺点:
// 1. 不能用于final字段
// 2. 难以进行单元测试
// 3. 隐藏了依赖关系
// 4. 违反了依赖注入原则
3.4 方法注入
/**
* 方法注入 - 处理作用域问题
*/
@Component
@Scope("singleton")
public abstract class CommandManager {
public void process() {
// 每次都获取新的Command实例
Command command = createCommand();
command.execute();
}
// 查找方法注入
@Lookup
protected abstract Command createCommand();
}
@Component
@Scope("prototype")
public class Command {
public void execute() {
System.out.println("执行命令");
}
}
四、Bean的生命周期
4.1 生命周期流程
Bean生命周期流程图
┌─────────────────────────────────────────┐
│ 1. 实例化Bean │
│ new XXX() │
├─────────────────────────────────────────┤
│ 2. 设置属性 │
│ populateBean() │
├─────────────────────────────────────────┤
│ 3. 调用BeanNameAware.setBeanName() │
├─────────────────────────────────────────┤
│ 4. 调用BeanFactoryAware.setBeanFactory│
├─────────────────────────────────────────┤
│ 5. 调用ApplicationContextAware │
├─────────────────────────────────────────┤
│ 6. 前置处理 │
│ BeanPostProcessor.postProcessBefore │
├─────────────────────────────────────────┤
│ 7. 调用InitializingBean.afterProperties│
├─────────────────────────────────────────┤
│ 8. 调用自定义init-method │
├─────────────────────────────────────────┤
│ 9. 后置处理 │
│ BeanPostProcessor.postProcessAfter │
├─────────────────────────────────────────┤
│ 10. Bean可以使用了 │
├─────────────────────────────────────────┤
│ 11. 容器关闭 │
├─────────────────────────────────────────┤
│ 12. 调用DisposableBean.destroy() │
├─────────────────────────────────────────┤
│ 13. 调用自定义destroy-method │
└─────────────────────────────────────────┘
4.2 生命周期回调
/**
* 完整的Bean生命周期示例
*/
@Component
public class LifecycleBean implements
BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
InitializingBean,
DisposableBean {
private String beanName;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
public LifecycleBean() {
System.out.println("1. 构造器执行");
}
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("2. BeanNameAware.setBeanName(): " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
System.out.println("3. BeanFactoryAware.setBeanFactory()");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
System.out.println("4. ApplicationContextAware.setApplicationContext()");
}
@PostConstruct
public void postConstruct() {
System.out.println("5. @PostConstruct注解的方法执行");
}
@Override
public void afterPropertiesSet() {
System.out.println("6. InitializingBean.afterPropertiesSet()");
}
public void customInit() {
System.out.println("7. 自定义init-method执行");
}
@PreDestroy
public void preDestroy() {
System.out.println("8. @PreDestroy注解的方法执行");
}
@Override
public void destroy() {
System.out.println("9. DisposableBean.destroy()");
}
public void customDestroy() {
System.out.println("10. 自定义destroy-method执行");
}
}
/**
* 配置Bean
*/
@Configuration
public class LifecycleConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public LifecycleBean lifecycleBean() {
return new LifecycleBean();
}
}
4.3 BeanPostProcessor
/**
* 自定义BeanPostProcessor
* 类似于Spring AOP的实现原理
*/
@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 Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("代理方法调用: " + method.getName());
return method.invoke(target, args);
}
);
}
}
五、Bean的作用域
5.1 常见作用域
/**
* 单例作用域(默认)
*/
@Service
@Scope("singleton") // 可以省略
public class SingletonService {
// 整个容器只有一个实例
}
/**
* 原型作用域
*/
@Service
@Scope("prototype")
public class PrototypeService {
// 每次获取都创建新实例
}
/**
* Web环境作用域
*/
@Controller
@Scope("request")
public class RequestController {
// 每个HTTP请求创建一个实例
}
@Controller
@Scope("session")
public class SessionController {
// 每个HTTP会话创建一个实例
}
@Controller
@Scope("application")
public class ApplicationController {
// 整个ServletContext一个实例
}
5.2 作用域对比
┌─────────────┬────────────────┬────────────────────┐
│ 作用域 │ 创建时机 │ 使用场景 │
├─────────────┼────────────────┼────────────────────┤
│ singleton │ 容器启动时 │ 无状态Bean │
│ prototype │ 每次getBean │ 有状态Bean │
│ request │ 每次HTTP请求 │ Web请求数据 │
│ session │ 每次会话 │ 用户会话数据 │
│ application│ ServletContext│ 应用全局数据 │
└─────────────┴────────────────┴────────────────────┘
5.3 作用域依赖问题
/**
* 单例Bean依赖原型Bean的问题
*/
@Service
@Scope("singleton")
public class SingletonBean {
// 问题:prototypeBean只会注入一次
@Autowired
private PrototypeBean prototypeBean;
public void doSomething() {
prototypeBean.execute();
}
}
/**
* 解决方案1:方法注入
*/
@Service
@Scope("singleton")
public abstract class SingletonBeanWithLookup {
public void doSomething() {
PrototypeBean bean = getPrototypeBean();
bean.execute();
}
@Lookup
protected abstract PrototypeBean getPrototypeBean();
}
/**
* 解决方案2:使用Provider
*/
@Service
@Scope("singleton")
public class SingletonBeanWithProvider {
@Autowired
private Provider<PrototypeBean> prototypeBeanProvider;
public void doSomething() {
PrototypeBean bean = prototypeBeanProvider.get();
bean.execute();
}
}
/**
* 解决方案3:ApplicationContext
*/
@Service
@Scope("singleton")
public class SingletonBeanWithContext {
@Autowired
private ApplicationContext context;
public void doSomething() {
PrototypeBean bean = context.getBean(PrototypeBean.class);
bean.execute();
}
}
六、自动装配
6.1 @Autowired注解
/**
* @Autowired的使用
*/
@Service
public class AutowiredDemo {
// 字段注入
@Autowired
private UserDao userDao;
// 构造器注入
private OrderDao orderDao;
@Autowired
public AutowiredDemo(OrderDao orderDao) {
this.orderDao = orderDao;
}
// Setter注入
private ProductDao productDao;
@Autowired
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
// 可选依赖
@Autowired(required = false)
private OptionalService optionalService;
// 集合注入
@Autowired
private List<MessageSender> senders;
@Autowired
private Map<String, PaymentStrategy> paymentStrategies;
}
6.2 @Qualifier注解
/**
* 使用@Qualifier指定具体的Bean
*/
public interface MessageSender {
void send(String message);
}
@Component("emailSender")
public class EmailSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("发送邮件: " + message);
}
}
@Component("smsSender")
public class SmsSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("发送短信: " + message);
}
}
@Service
public class NotificationService {
// 使用@Qualifier指定具体的实现
@Autowired
@Qualifier("emailSender")
private MessageSender emailSender;
@Autowired
@Qualifier("smsSender")
private MessageSender smsSender;
public void notify(String message, String channel) {
if ("email".equals(channel)) {
emailSender.send(message);
} else if ("sms".equals(channel)) {
smsSender.send(message);
}
}
}
6.3 @Primary注解
/**
* 使用@Primary设置首选Bean
*/
@Component
@Primary // 默认注入这个实现
public class PrimaryEmailSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("主要邮件发送器: " + message);
}
}
@Component
public class BackupEmailSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("备用邮件发送器: " + message);
}
}
@Service
public class EmailService {
// 自动注入@Primary标记的Bean
@Autowired
private MessageSender sender; // 注入PrimaryEmailSender
}
6.4 @Resource vs @Autowired
/**
* @Resource和@Autowired的区别
*/
@Service
public class ResourceDemo {
// @Autowired: 按类型装配(Spring注解)
@Autowired
private UserDao userDao;
// @Resource: 按名称装配(JSR-250标准)
@Resource(name = "userDaoImpl")
private UserDao userDaoByName;
// @Inject: 按类型装配(JSR-330标准)
@Inject
private OrderDao orderDao;
}
┌──────────────┬─────────────┬──────────────┬────────────┐
│ 注解 │ 来源 │ 装配方式 │ required │
├──────────────┼─────────────┼──────────────┼────────────┤
│ @Autowired │ Spring │ 类型优先 │ 支持 │
│ @Resource │ JSR-250 │ 名称优先 │ 不支持 │
│ @Inject │ JSR-330 │ 类型优先 │ 不支持 │
└──────────────┴─────────────┴──────────────┴────────────┘
七、实战案例
7.1 案例1:多数据源配置
/**
* 主数据源配置
*/
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "primaryJdbcTemplate")
public JdbcTemplate primaryJdbcTemplate(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "secondaryJdbcTemplate")
public JdbcTemplate secondaryJdbcTemplate(
@Qualifier("secondaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
/**
* 使用多数据源
*/
@Repository
public class MultiDataSourceDao {
@Autowired
@Qualifier("primaryJdbcTemplate")
private JdbcTemplate primaryJdbcTemplate;
@Autowired
@Qualifier("secondaryJdbcTemplate")
private JdbcTemplate secondaryJdbcTemplate;
public User findUserFromPrimary(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return primaryJdbcTemplate.queryForObject(sql,
new BeanPropertyRowMapper<>(User.class), id);
}
public Order findOrderFromSecondary(Long id) {
String sql = "SELECT * FROM orders WHERE id = ?";
return secondaryJdbcTemplate.queryForObject(sql,
new BeanPropertyRowMapper<>(Order.class), id);
}
}
7.2 案例2:策略模式与IoC
/**
* 策略接口
*/
public interface PaymentStrategy {
boolean support(String paymentType);
void pay(Order order);
}
/**
* 支付宝策略
*/
@Component
public class AlipayStrategy implements PaymentStrategy {
@Override
public boolean support(String paymentType) {
return "ALIPAY".equals(paymentType);
}
@Override
public void pay(Order order) {
System.out.println("使用支付宝支付订单: " + order.getId());
}
}
/**
* 微信策略
*/
@Component
public class WechatStrategy implements PaymentStrategy {
@Override
public boolean support(String paymentType) {
return "WECHAT".equals(paymentType);
}
@Override
public void pay(Order order) {
System.out.println("使用微信支付订单: " + order.getId());
}
}
/**
* 策略管理器
*/
@Service
public class PaymentStrategyManager {
// Spring自动注入所有PaymentStrategy实现
@Autowired
private List<PaymentStrategy> strategies;
public void pay(Order order, String paymentType) {
PaymentStrategy strategy = strategies.stream()
.filter(s -> s.support(paymentType))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("不支持的支付方式"));
strategy.pay(order);
}
}
/**
* 使用示例
*/
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private PaymentStrategyManager paymentManager;
@PostMapping("/{id}/pay")
public void payOrder(@PathVariable Long id, @RequestParam String paymentType) {
Order order = new Order(id);
paymentManager.pay(order, paymentType);
}
}
7.3 案例3:条件化配置
/**
* 自定义条件注解
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
String name();
String havingValue() default "";
}
/**
* 条件判断类
*/
public class OnPropertyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes =
metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName());
String propertyName = (String) attributes.get("name");
String expectedValue = (String) attributes.get("havingValue");
Environment env = context.getEnvironment();
String actualValue = env.getProperty(propertyName);
return expectedValue.equals(actualValue);
}
}
/**
* 使用条件化配置
*/
@Configuration
public class CacheConfig {
@Bean
@ConditionalOnProperty(name = "cache.type", havingValue = "redis")
public CacheService redisCacheService() {
return new RedisCacheService();
}
@Bean
@ConditionalOnProperty(name = "cache.type", havingValue = "memory")
public CacheService memoryCacheService() {
return new MemoryCacheService();
}
@Bean
@ConditionalOnMissingBean(CacheService.class)
public CacheService defaultCacheService() {
return new MemoryCacheService();
}
}
7.4 案例4:事件驱动
/**
* 自定义事件
*/
public class UserRegisteredEvent extends ApplicationEvent {
private User user;
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* 事件监听器1:发送欢迎邮件
*/
@Component
public class WelcomeEmailListener {
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
System.out.println("发送欢迎邮件给: " + user.getEmail());
}
}
/**
* 事件监听器2:赠送优惠券
*/
@Component
public class CouponListener {
@EventListener
@Async // 异步处理
public void handleUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
System.out.println("为新用户赠送优惠券: " + user.getId());
}
}
/**
* 事件发布者
*/
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void register(User user) {
// 保存用户
saveUser(user);
// 发布事件
UserRegisteredEvent event = new UserRegisteredEvent(this, user);
eventPublisher.publishEvent(event);
}
private void saveUser(User user) {
System.out.println("保存用户: " + user.getUsername());
}
}
八、源码分析
8.1 容器启动流程
/**
* ApplicationContext启动流程简化版
*/
public class SimpleApplicationContext {
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
public void refresh() {
// 1. 准备BeanFactory
prepareBeanFactory();
// 2. 加载Bean定义
loadBeanDefinitions();
// 3. 实例化所有单例Bean
finishBeanFactoryInitialization();
// 4. 完成刷新
finishRefresh();
}
private void prepareBeanFactory() {
System.out.println("准备BeanFactory");
}
private void loadBeanDefinitions() {
System.out.println("加载Bean定义");
// 扫描@Component、@Service等注解
// 解析@Bean方法
// 读取XML配置
}
private void finishBeanFactoryInitialization() {
System.out.println("实例化单例Bean");
for (String beanName : beanDefinitionMap.keySet()) {
getBean(beanName);
}
}
private void finishRefresh() {
System.out.println("完成刷新,发布事件");
}
public Object getBean(String name) {
// 从缓存获取
Object bean = singletonObjects.get(name);
if (bean != null) {
return bean;
}
// 创建Bean
BeanDefinition bd = beanDefinitionMap.get(name);
bean = createBean(bd);
// 放入缓存
singletonObjects.put(name, bean);
return bean;
}
private Object createBean(BeanDefinition bd) {
// 1. 实例化
Object bean = instantiate(bd);
// 2. 属性注入
populateBean(bean, bd);
// 3. 初始化
initializeBean(bean, bd);
return bean;
}
private Object instantiate(BeanDefinition bd) {
// 反射创建对象
return null;
}
private void populateBean(Object bean, BeanDefinition bd) {
// 注入依赖
}
private void initializeBean(Object bean, BeanDefinition bd) {
// 调用初始化方法
}
}
8.2 循环依赖解决
/**
* 三级缓存解决循环依赖
*/
public class CircularDependencyResolver {
// 一级缓存:成品对象
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// 二级缓存:半成品对象
private Map<String, Object> earlySingletonObjects = new HashMap<>();
// 三级缓存:对象工厂
private Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
public Object getBean(String beanName) {
// 先从一级缓存获取
Object bean = singletonObjects.get(beanName);
if (bean != null) {
return bean;
}
// 再从二级缓存获取
bean = earlySingletonObjects.get(beanName);
if (bean != null) {
return bean;
}
// 从三级缓存获取
ObjectFactory<?> factory = singletonFactories.get(beanName);
if (factory != null) {
bean = factory.getObject();
earlySingletonObjects.put(beanName, bean);
singletonFactories.remove(beanName);
return bean;
}
// 创建Bean
return createBean(beanName);
}
private Object createBean(String beanName) {
// 1. 实例化
Object bean = new Object();
// 2. 提前暴露(放入三级缓存)
singletonFactories.put(beanName, () -> bean);
// 3. 属性注入(可能触发循环依赖)
populateBean(bean);
// 4. 初始化完成,放入一级缓存
singletonObjects.put(beanName, bean);
earlySingletonObjects.remove(beanName);
singletonFactories.remove(beanName);
return bean;
}
private void populateBean(Object bean) {
// 注入依赖
}
}
循环依赖解决流程
┌─────────────────────────────────────────┐
│ A依赖B,B依赖A │
├─────────────────────────────────────────┤
│ 1. 创建A,放入三级缓存 │
│ 2. 注入B到A │
│ 3. 创建B,放入三级缓存 │
│ 4. 注入A到B(从三级缓存获取A) │
│ 5. B初始化完成,放入一级缓存 │
│ 6. A初始化完成,放入一级缓存 │
└─────────────────────────────────────────┘
九、最佳实践
9.1 依赖注入建议
/**
* ✅ 推荐:使用构造器注入
*/
@Service
public class GoodService {
private final UserDao userDao;
private final OrderDao orderDao;
public GoodService(UserDao userDao, OrderDao orderDao) {
this.userDao = userDao;
this.orderDao = orderDao;
}
}
/**
* ❌ 不推荐:字段注入
*/
@Service
public class BadService {
@Autowired
private UserDao userDao;
@Autowired
private OrderDao orderDao;
}
9.2 Bean命名规范
/**
* Bean命名建议
*/
@Configuration
public class BeanNamingConfig {
// ✅ 好的命名:清晰表达用途
@Bean
public DataSource primaryDataSource() {
return new HikariDataSource();
}
@Bean
public ThreadPoolExecutor asyncTaskExecutor() {
return new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
}
// ❌ 不好的命名:含义不清
@Bean
public DataSource ds1() {
return new HikariDataSource();
}
}
9.3 避免循环依赖
/**
* ❌ 避免构造器循环依赖
*/
@Service
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
@Service
public class ServiceB {
private final ServiceA serviceA;
public ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
}
/**
* ✅ 解决方案:重新设计
*/
@Service
public class ServiceA {
private final CommonService commonService;
public ServiceA(CommonService commonService) {
this.commonService = commonService;
}
}
@Service
public class ServiceB {
private final CommonService commonService;
public ServiceB(CommonService commonService) {
this.commonService = commonService;
}
}
十、总结
核心知识点回顾
Spring IoC核心要点
│
├── 核心概念
│ ├── IoC(控制反转)
│ ├── DI(依赖注入)
│ └── 容器(BeanFactory/ApplicationContext)
│
├── 配置方式
│ ├── XML配置
│ ├── 注解配置
│ └── Java配置
│
├── 依赖注入
│ ├── 构造器注入(推荐)
│ ├── Setter注入
│ └── 字段注入
│
├── Bean管理
│ ├── 生命周期
│ ├── 作用域
│ └── 自动装配
│
└── 高级特性
├── 条件化配置
├── 事件机制
└── 循环依赖解决
Spring IoC容器是Spring框架的核心,掌握IoC的原理和使用,是深入学习Spring其他特性的基础。在实际开发中,要灵活运用IoC的各种特性,编写松耦合、易测试、可维护的代码。