网站建设公司江西,深圳建站服务中心,视频网站移动端,沈阳学网站制作学校Spring如何解决循环依赖#xff1a;深入理解三级缓存机制
引言
在我们之前的文章中#xff0c;我们探讨了什么是循环依赖以及它带来的问题。作为Java生态系统中最重要的框架之一#xff0c;Spring Framework在处理循环依赖方面有着独特而精妙的解决方案。今天#xff0c;让…Spring如何解决循环依赖深入理解三级缓存机制
引言
在我们之前的文章中我们探讨了什么是循环依赖以及它带来的问题。作为Java生态系统中最重要的框架之一Spring Framework在处理循环依赖方面有着独特而精妙的解决方案。今天让我们深入了解Spring是如何通过三级缓存机制巧妙地解决循环依赖问题的。
Spring中的循环依赖场景
典型的循环依赖示例
Component
public class ServiceA {Autowiredprivate ServiceB serviceB;public void doSomething() {System.out.println(ServiceA doing something);serviceB.doSomething();}
}Component
public class ServiceB {Autowiredprivate ServiceC serviceC;public void doSomething() {System.out.println(ServiceB doing something);serviceC.doSomething();}
}Component
public class ServiceC {Autowiredprivate ServiceA serviceA; // 形成循环依赖A - B - C - Apublic void doSomething() {System.out.println(ServiceC doing something);serviceA.doSomething();}
}构造器循环依赖Spring无法解决
Component
public class ServiceA {private final ServiceB serviceB;// 构造器注入形成的循环依赖Spring无法解决public ServiceA(ServiceB serviceB) {this.serviceB serviceB;}
}Component
public class ServiceB {private final ServiceA serviceA;public ServiceB(ServiceA serviceA) {this.serviceA serviceA;}
}Spring Bean的生命周期
要理解Spring如何解决循环依赖首先需要了解Bean的创建过程
public class SpringBeanLifecycle {/*** Spring Bean的完整生命周期*/public Object createBean(String beanName, BeanDefinition beanDefinition) {// 1. 实例化 - 创建对象实例调用构造器Object bean instantiateBean(beanName, beanDefinition);// 2. 属性填充 - 依赖注入populateBean(bean, beanName, beanDefinition);// 3. 初始化 - 调用初始化方法initializeBean(bean, beanName);return bean;}private Object instantiateBean(String beanName, BeanDefinition bd) {// 通过反射创建实例Constructor? constructor bd.getBeanClass().getDeclaredConstructor();return constructor.newInstance();}private void populateBean(Object bean, String beanName, BeanDefinition bd) {// 处理Autowired、Resource等注解// 这里会触发依赖Bean的创建Field[] fields bean.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(Autowired.class)) {Object dependency getBean(field.getType());field.setAccessible(true);field.set(bean, dependency);}}}private void initializeBean(Object bean, String beanName) {// 调用初始化回调方法if (bean instanceof InitializingBean) {((InitializingBean) bean).afterPropertiesSet();}}
}Spring的三级缓存机制
Spring通过三级缓存来解决单例Bean的循环依赖问题
public class DefaultSingletonBeanRegistry {/** 一级缓存完成初始化的单例Bean */private final MapString, Object singletonObjects new ConcurrentHashMap(256);/** 二级缓存完成实例化但未完成初始化的Bean */private final MapString, Object earlySingletonObjects new HashMap(16);/** 三级缓存单例Bean的工厂 */private final MapString, ObjectFactory? singletonFactories new HashMap(16);/** 正在创建的Bean名称集合 */private final SetString singletonsCurrentlyInCreation Collections.newSetFromMap(new ConcurrentHashMap(16));/*** 获取单例Bean的核心方法*/protected Object getSingleton(String beanName) {return getSingleton(beanName, true);}protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 1. 从一级缓存中获取完全初始化的BeanObject singletonObject this.singletonObjects.get(beanName);if (singletonObject null isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {// 2. 从二级缓存中获取早期Bean引用singletonObject this.earlySingletonObjects.get(beanName);if (singletonObject null allowEarlyReference) {// 3. 从三级缓存中获取Bean工厂ObjectFactory? singletonFactory this.singletonFactories.get(beanName);if (singletonFactory ! null) {// 调用工厂方法创建早期Bean引用singletonObject singletonFactory.getObject();// 将早期Bean引用放入二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 从三级缓存中移除this.singletonFactories.remove(beanName);}}}}return singletonObject;}/*** 添加单例Bean工厂到三级缓存*/protected void addSingletonFactory(String beanName, ObjectFactory? singletonFactory) {synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);}}}/*** 将完全初始化的Bean添加到一级缓存*/protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);}}
}循环依赖解决过程详解
让我们通过一个具体的例子来看看Spring是如何解决循环依赖的
/*** 模拟Spring解决循环依赖的完整过程*/
public class CircularDependencyResolver {// 三级缓存private MapString, Object singletonObjects new ConcurrentHashMap();private MapString, Object earlySingletonObjects new HashMap();private MapString, ObjectFactory? singletonFactories new HashMap();private SetString singletonsCurrentlyInCreation new HashSet();/*** 创建Bean的主要方法*/public Object getBean(String beanName) {// 先尝试从缓存中获取Object singleton getSingleton(beanName);if (singleton ! null) {return singleton;}// 缓存中没有开始创建return createBean(beanName);}private Object createBean(String beanName) {// 标记Bean正在创建中singletonsCurrentlyInCreation.add(beanName);try {// 1. 实例化BeanObject bean instantiateBean(beanName);// 2. 将Bean工厂放入三级缓存关键步骤addSingletonFactory(beanName, () - getEarlyBeanReference(beanName, bean));// 3. 属性填充可能触发循环依赖populateBean(bean, beanName);// 4. 初始化BeaninitializeBean(bean, beanName);// 5. 将完成的Bean放入一级缓存addSingleton(beanName, bean);return bean;} finally {// 移除创建中标记singletonsCurrentlyInCreation.remove(beanName);}}private Object instantiateBean(String beanName) {// 模拟通过反射创建Bean实例System.out.println(实例化Bean: beanName);if (serviceA.equals(beanName)) {return new ServiceA();} else if (serviceB.equals(beanName)) {return new ServiceB();}throw new RuntimeException(Unknown bean: beanName);}private void populateBean(Object bean, String beanName) {System.out.println(填充Bean属性: beanName);// 模拟依赖注入if (bean instanceof ServiceA) {ServiceA serviceA (ServiceA) bean;// 注入ServiceB这里会触发ServiceB的创建Object serviceB getBean(serviceB);serviceA.setServiceB((ServiceB) serviceB);} else if (bean instanceof ServiceB) {ServiceB serviceB (ServiceB) bean;// 注入ServiceA这里会从缓存中获取早期引用Object serviceA getBean(serviceA);serviceB.setServiceA((ServiceA) serviceA);}}private void initializeBean(Object bean, String beanName) {System.out.println(初始化Bean: beanName);// 执行初始化逻辑}/*** 获取早期Bean引用处理AOP代理*/private Object getEarlyBeanReference(String beanName, Object bean) {System.out.println(获取早期Bean引用: beanName);// 如果需要AOP代理在这里创建代理对象if (needsProxy(beanName)) {return createProxy(bean);}return bean;}private boolean needsProxy(String beanName) {// 简化的代理判断逻辑return beanName.contains(service);}private Object createProxy(Object target) {// 简化的代理创建逻辑System.out.println(创建代理对象: target.getClass().getSimpleName());return target; // 实际应该返回代理对象}// 其他辅助方法...private Object getSingleton(String beanName) {Object singletonObject singletonObjects.get(beanName);if (singletonObject null singletonsCurrentlyInCreation.contains(beanName)) {singletonObject earlySingletonObjects.get(beanName);if (singletonObject null) {ObjectFactory? singletonFactory singletonFactories.get(beanName);if (singletonFactory ! null) {singletonObject singletonFactory.getObject();earlySingletonObjects.put(beanName, singletonObject);singletonFactories.remove(beanName);}}}return singletonObject;}private void addSingletonFactory(String beanName, ObjectFactory? singletonFactory) {if (!singletonObjects.containsKey(beanName)) {singletonFactories.put(beanName, singletonFactory);earlySingletonObjects.remove(beanName);}}private void addSingleton(String beanName, Object singletonObject) {singletonObjects.put(beanName, singletonObject);singletonFactories.remove(beanName);earlySingletonObjects.remove(beanName);}
}循环依赖解决的时序图
ServiceA创建过程:
1. 实例化ServiceA
2. 将ServiceA工厂放入三级缓存
3. 填充ServiceA属性需要ServiceB|├─ ServiceB创建过程:│ 1. 实例化ServiceB │ 2. 将ServiceB工厂放入三级缓存│ 3. 填充ServiceB属性需要ServiceA│ 4. 从三级缓存获取ServiceA早期引用│ 5. 完成ServiceB初始化放入一级缓存│
4. 获得ServiceB实例完成ServiceA属性填充
5. 完成ServiceA初始化放入一级缓存为什么需要三级缓存
只有一级缓存的问题
public class SingleCacheExample {private MapString, Object singletonObjects new ConcurrentHashMap();public Object getBean(String beanName) {Object bean singletonObjects.get(beanName);if (bean ! null) {return bean;}// 创建Beanbean createBean(beanName);singletonObjects.put(beanName, bean);return bean;}// 问题在Bean完全创建完成之前其他Bean无法获取到它的引用// 导致循环依赖无法解决
}只有二级缓存的问题
public class TwoCacheExample {private MapString, Object singletonObjects new ConcurrentHashMap();private MapString, Object earlySingletonObjects new HashMap();// 问题无法处理AOP代理的情况// 如果Bean需要被代理早期引用和最终对象可能不是同一个实例
}三级缓存的优势
/*** 三级缓存解决的问题* 1. 一级缓存存储完全初始化的Bean* 2. 二级缓存存储早期Bean引用解决循环依赖* 3. 三级缓存存储Bean工厂延迟决定是否需要代理*/
public class ThreeCacheAdvantages {/*** 三级缓存的关键作用* 1. 延迟代理对象的创建* 2. 确保循环依赖中代理对象的一致性* 3. 避免不必要的代理对象创建*/private Object getEarlyBeanReference(String beanName, Object bean) {// 只有在真正需要早期引用时才决定是否创建代理if (hasCircularDependency(beanName)) {if (needsProxy(beanName)) {return createProxy(bean);}}return bean;}
}AOP与循环依赖
Spring AOP为循环依赖的解决增加了复杂性
Component
Service
public class UserService {Autowiredprivate OrderService orderService;Transactional // 这个注解会导致创建AOP代理public void createUser(User user) {// 业务逻辑orderService.createDefaultOrder(user);}
}Component
Service
public class OrderService {Autowiredprivate UserService userService;Transactionalpublic void createDefaultOrder(User user) {// 业务逻辑userService.validateUser(user);}
}AOP代理处理过程
public class AopCircularDependencyHandler {/*** 处理AOP代理的循环依赖*/public Object resolveAopCircularDependency(String beanName, Object bean) {// 1. 检查是否需要创建代理if (shouldCreateProxy(bean)) {// 2. 创建代理对象Object proxy createAopProxy(bean);// 3. 确保早期引用和最终对象的一致性ensureProxyConsistency(beanName, bean, proxy);return proxy;}return bean;}private boolean shouldCreateProxy(Object bean) {// 检查是否有Transactional、Async等注解Class? beanClass bean.getClass();// 检查类级别注解if (beanClass.isAnnotationPresent(Transactional.class) ||beanClass.isAnnotationPresent(Async.class)) {return true;}// 检查方法级别注解Method[] methods beanClass.getDeclaredMethods();for (Method method : methods) {if (method.isAnnotationPresent(Transactional.class) ||method.isAnnotationPresent(Async.class)) {return true;}}return false;}private Object createAopProxy(Object target) {// 使用CGLIB或JDK动态代理创建代理对象ProxyFactory proxyFactory new ProxyFactory(target);// 添加事务拦截器proxyFactory.addAdvice(new TransactionInterceptor());return proxyFactory.getProxy();}
}Spring无法解决的循环依赖场景
1. 构造器循环依赖
Component
public class ServiceA {private final ServiceB serviceB;// Spring无法解决构造器循环依赖public ServiceA(ServiceB serviceB) {this.serviceB serviceB;}
}Component
public class ServiceB {private final ServiceA serviceA;public ServiceB(ServiceA serviceA) {this.serviceA serviceA;}
}// 启动时会抛出异常
// BeanCurrentlyInCreationException: Error creating bean with name serviceA:
// Requested bean is currently in creation: Is there an unresolvable circular reference?2. prototype作用域的循环依赖
Component
Scope(prototype)
public class PrototypeServiceA {Autowiredprivate PrototypeServiceB serviceB;
}Component
Scope(prototype)
public class PrototypeServiceB {Autowiredprivate PrototypeServiceA serviceA;
}// prototype作用域的Bean每次都会创建新实例无法使用缓存解决循环依赖3. Async注解的特殊情况
Component
public class AsyncServiceA {Autowiredprivate AsyncServiceB serviceB;Asyncpublic void doAsync() {serviceB.doSomething();}
}Component
public class AsyncServiceB {Autowiredprivate AsyncServiceA serviceA;public void doSomething() {serviceA.doAsync();}
}// 在某些情况下Async可能导致循环依赖解决失败循环依赖的解决方案
1. 使用Lazy注解
Component
public class ServiceA {private final ServiceB serviceB;// 使用Lazy延迟注入打破循环依赖public ServiceA(Lazy ServiceB serviceB) {this.serviceB serviceB;}
}Component
public class ServiceB {private final ServiceA serviceA;public ServiceB(ServiceA serviceA) {this.serviceA serviceA;}
}2. 使用Setter注入替代构造器注入
Component
public class ServiceA {private ServiceB serviceB;// 使用Setter注入替代构造器注入Autowiredpublic void setServiceB(ServiceB serviceB) {this.serviceB serviceB;}
}Component
public class ServiceB {private ServiceA serviceA;Autowiredpublic void setServiceA(ServiceA serviceA) {this.serviceA serviceA;}
}3. 使用PostConstruct
Component
public class ServiceA {Autowiredprivate ServiceB serviceB;private ServiceA selfReference;PostConstructpublic void init() {// 在初始化阶段设置自引用this.selfReference this;}
}4. 重新设计架构
// 原始设计循环依赖
Component
public class UserService {Autowiredprivate OrderService orderService;public void processUser(User user) {orderService.processOrder(user.getOrders());}
}Component
public class OrderService {Autowiredprivate UserService userService;public void processOrder(ListOrder orders) {for (Order order : orders) {userService.validateUser(order.getUser());}}
}// 重构后提取公共服务
Component
public class ValidationService {public void validateUser(User user) {// 用户验证逻辑}public void validateOrder(Order order) {// 订单验证逻辑}
}Component
public class UserService {Autowiredprivate ValidationService validationService;public void processUser(User user) {validationService.validateUser(user);// 处理用户逻辑}
}Component
public class OrderService {Autowiredprivate ValidationService validationService;public void processOrder(Order order) {validationService.validateOrder(order);// 处理订单逻辑}
}循环依赖检测和调试
1. 启用循环依赖检测
Configuration
EnableAutoConfiguration
public class AppConfig {Beanpublic static BeanFactoryPostProcessor circularDependencyDetector() {return new BeanFactoryPostProcessor() {Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {if (beanFactory instanceof DefaultListableBeanFactory) {DefaultListableBeanFactory factory (DefaultListableBeanFactory) beanFactory;factory.setAllowCircularReferences(false); // 禁用循环依赖}}};}
}2. 自定义循环依赖检测器
Component
public class CircularDependencyDetector implements BeanPostProcessor {private final SetString beansInCreation new HashSet();private final MapString, SetString dependencyGraph new HashMap();Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {detectCircularDependency(beanName);return bean;}private void detectCircularDependency(String beanName) {if (beansInCreation.contains(beanName)) {throw new BeanCurrentlyInCreationException(Circular dependency detected: beanName);}beansInCreation.add(beanName);// 分析依赖关系analyzeDependencies(beanName);beansInCreation.remove(beanName);}private void analyzeDependencies(String beanName) {// 通过反射分析Bean的依赖关系// 构建依赖图检测环路}
}3. 循环依赖调试工具
Component
public class CircularDependencyDebugger {private static final Logger logger LoggerFactory.getLogger(CircularDependencyDebugger.class);EventListenerpublic void handleContextRefreshed(ContextRefreshedEvent event) {ApplicationContext context event.getApplicationContext();// 分析所有Bean的依赖关系analyzeBeanDependencies(context);}private void analyzeBeanDependencies(ApplicationContext context) {String[] beanNames context.getBeanDefinitionNames();for (String beanName : beanNames) {try {BeanDefinition beanDefinition ((ConfigurableApplicationContext) context).getBeanFactory().getBeanDefinition(beanName);// 分析依赖关系SetString dependencies extractDependencies(beanDefinition);logger.info(Bean {} depends on: {}, beanName, dependencies);} catch (Exception e) {logger.warn(Failed to analyze dependencies for bean: {}, beanName, e);}}}private SetString extractDependencies(BeanDefinition beanDefinition) {SetString dependencies new HashSet();// 提取构造器依赖ConstructorArgumentValues constructorArgs beanDefinition.getConstructorArgumentValues();for (ConstructorArgumentValues.ValueHolder valueHolder : constructorArgs.getGenericArgumentValues()) {if (valueHolder.getValue() instanceof RuntimeBeanReference) {RuntimeBeanReference ref (RuntimeBeanReference) valueHolder.getValue();dependencies.add(ref.getBeanName());}}// 提取属性依赖MutablePropertyValues propertyValues beanDefinition.getPropertyValues();for (PropertyValue pv : propertyValues.getPropertyValues()) {if (pv.getValue() instanceof RuntimeBeanReference) {RuntimeBeanReference ref (RuntimeBeanReference) pv.getValue();dependencies.add(ref.getBeanName());}}return dependencies;}
}性能考虑
1. 三级缓存的性能影响
public class CachePerformanceAnalysis {/*** 分析三级缓存对性能的影响*/public void analyzePerformance() {// 1. 内存开销三个Map需要额外的内存// 2. 查找开销需要依次查找三个缓存// 3. 同步开销缓存操作需要同步long startTime System.nanoTime();// 模拟缓存查找Object bean getSingletonFromCache(testBean);long endTime System.nanoTime();long duration endTime - startTime;System.out.println(缓存查找耗时: duration 纳秒);}private Object getSingletonFromCache(String beanName) {// 三级缓存查找的性能开销Object singleton singletonObjects.get(beanName);if (singleton null) {singleton earlySingletonObjects.get(beanName);if (singleton null) {ObjectFactory? factory singletonFactories.get(beanName);if (factory ! null) {singleton factory.getObject();}}}return singleton;}
}2. 优化建议
Configuration
public class CircularDependencyOptimization {/*** 优化循环依赖处理的配置*/Beanpublic static BeanFactoryPostProcessor optimizeCircularDependency() {return beanFactory - {if (beanFactory instanceof DefaultListableBeanFactory) {DefaultListableBeanFactory factory (DefaultListableBeanFactory) beanFactory;// 1. 预分析Bean依赖关系提前发现循环依赖preAnalyzeDependencies(factory);// 2. 优化缓存大小optimizeCacheSize(factory);// 3. 启用并发优化enableConcurrentOptimization(factory);}};}javaprivate static void preAnalyzeDependencies(DefaultListableBeanFactory factory) {String[] beanNames factory.getBeanDefinitionNames();MapString, SetString dependencyGraph new HashMap();// 构建依赖图for (String beanName : beanNames) {BeanDefinition bd factory.getBeanDefinition(beanName);SetString dependencies extractBeanDependencies(bd);dependencyGraph.put(beanName, dependencies);}// 检测循环依赖detectCycles(dependencyGraph);}private static void detectCycles(MapString, SetString graph) {SetString visited new HashSet();SetString recursionStack new HashSet();for (String node : graph.keySet()) {if (hasCycle(graph, node, visited, recursionStack)) {System.out.println(检测到循环依赖涉及Bean: node);}}}private static boolean hasCycle(MapString, SetString graph, String node, SetString visited, SetString recursionStack) {if (recursionStack.contains(node)) {return true; // 发现环路}if (visited.contains(node)) {return false; // 已经访问过无环路}visited.add(node);recursionStack.add(node);SetString neighbors graph.get(node);if (neighbors ! null) {for (String neighbor : neighbors) {if (hasCycle(graph, neighbor, visited, recursionStack)) {return true;}}}recursionStack.remove(node);return false;}private static void optimizeCacheSize(DefaultListableBeanFactory factory) {// 根据Bean数量优化缓存初始容量int beanCount factory.getBeanDefinitionCount();int optimalCacheSize Math.max(16, beanCount / 4);// 这里可以通过反射设置缓存的初始容量// 实际实现中需要访问私有字段}private static void enableConcurrentOptimization(DefaultListableBeanFactory factory) {// 启用并发创建Bean的优化factory.setAllowEagerClassLoading(true);factory.setAllowRawInjectionDespiteWrapping(true);}
}实际应用案例
案例1微服务中的循环依赖
/*** 微服务架构中常见的循环依赖场景*/
Service
public class UserService {Autowiredprivate OrderService orderService;Autowiredprivate NotificationService notificationService;Transactionalpublic User createUser(CreateUserRequest request) {User user new User(request);user userRepository.save(user);// 创建用户后创建默认订单orderService.createWelcomeOrder(user);// 发送欢迎通知notificationService.sendWelcomeNotification(user);return user;}
}Service
public class OrderService {Autowiredprivate UserService userService; // 循环依赖Autowiredprivate PaymentService paymentService;Transactionalpublic Order createWelcomeOrder(User user) {Order order new Order(user, getWelcomeProducts());order orderRepository.save(order);// 更新用户的订单统计userService.updateOrderStatistics(user.getId());return order;}
}Service
public class NotificationService {Autowiredprivate UserService userService; // 另一个循环依赖public void sendWelcomeNotification(User user) {// 获取用户偏好设置UserPreference preference userService.getUserPreference(user.getId());if (preference.isEmailEnabled()) {emailService.sendWelcomeEmail(user);}if (preference.isSmsEnabled()) {smsService.sendWelcomeSms(user);}}
}解决方案
/*** 重构后的解决方案使用事件驱动架构*/
Service
public class UserService {Autowiredprivate ApplicationEventPublisher eventPublisher;Transactionalpublic User createUser(CreateUserRequest request) {User user new User(request);user userRepository.save(user);// 发布用户创建事件而不是直接调用其他服务eventPublisher.publishEvent(new UserCreatedEvent(user));return user;}public void updateOrderStatistics(Long userId) {// 更新用户订单统计User user userRepository.findById(userId);user.incrementOrderCount();userRepository.save(user);}public UserPreference getUserPreference(Long userId) {return userPreferenceRepository.findByUserId(userId);}
}Service
public class OrderService {// 移除对UserService的直接依赖EventListenerAsyncpublic void handleUserCreated(UserCreatedEvent event) {createWelcomeOrder(event.getUser());}Transactionalpublic Order createWelcomeOrder(User user) {Order order new Order(user, getWelcomeProducts());order orderRepository.save(order);// 发布订单创建事件eventPublisher.publishEvent(new OrderCreatedEvent(order));return order;}
}Service
public class NotificationService {// 移除对UserService的直接依赖Autowiredprivate UserPreferenceRepository userPreferenceRepository;EventListenerAsyncpublic void handleUserCreated(UserCreatedEvent event) {sendWelcomeNotification(event.getUser());}public void sendWelcomeNotification(User user) {// 直接查询用户偏好避免循环依赖UserPreference preference userPreferenceRepository.findByUserId(user.getId());if (preference.isEmailEnabled()) {emailService.sendWelcomeEmail(user);}if (preference.isSmsEnabled()) {smsService.sendWelcomeSms(user);}}
}// 事件定义
public class UserCreatedEvent extends ApplicationEvent {private final User user;public UserCreatedEvent(Object source, User user) {super(source);this.user user;}public User getUser() {return user;}
}案例2复杂的业务场景循环依赖
/*** 电商系统中的复杂循环依赖场景*/
Service
public class ProductService {Autowiredprivate CategoryService categoryService;Autowiredprivate InventoryService inventoryService;Autowiredprivate PriceService priceService;public ProductDTO getProductDetails(Long productId) {Product product productRepository.findById(productId);// 获取分类信息Category category categoryService.getCategoryWithProducts(product.getCategoryId());// 获取库存信息Inventory inventory inventoryService.getInventoryWithProductInfo(productId);// 获取价格信息Price price priceService.getPriceWithProductDetails(productId);return ProductDTO.builder().product(product).category(category).inventory(inventory).price(price).build();}
}Service
public class CategoryService {Autowiredprivate ProductService productService; // 循环依赖public Category getCategoryWithProducts(Long categoryId) {Category category categoryRepository.findById(categoryId);// 获取分类下的热门产品ListProductDTO hotProducts productService.getHotProductsByCategory(categoryId);category.setHotProducts(hotProducts);return category;}
}Service
public class InventoryService {Autowiredprivate ProductService productService; // 循环依赖public Inventory getInventoryWithProductInfo(Long productId) {Inventory inventory inventoryRepository.findByProductId(productId);// 获取产品基本信息用于库存展示ProductDTO productInfo productService.getBasicProductInfo(productId);inventory.setProductInfo(productInfo);return inventory;}
}解决方案使用Repository模式和DTO组装器
/*** 重构后的解决方案分离数据访问和业务逻辑*/
Service
public class ProductQueryService {Autowiredprivate ProductRepository productRepository;Autowiredprivate CategoryRepository categoryRepository;Autowiredprivate InventoryRepository inventoryRepository;Autowiredprivate PriceRepository priceRepository;Autowiredprivate ProductDTOAssembler productDTOAssembler;/*** 获取完整的产品信息避免循环依赖*/public ProductDTO getProductDetails(Long productId) {// 1. 获取基础数据Product product productRepository.findById(productId);Category category categoryRepository.findById(product.getCategoryId());Inventory inventory inventoryRepository.findByProductId(productId);Price price priceRepository.findByProductId(productId);// 2. 组装DTOreturn productDTOAssembler.assemble(product, category, inventory, price);}
}Component
public class ProductDTOAssembler {public ProductDTO assemble(Product product, Category category, Inventory inventory, Price price) {return ProductDTO.builder().id(product.getId()).name(product.getName()).description(product.getDescription()).categoryName(category.getName()).categoryPath(category.getPath()).stockQuantity(inventory.getQuantity()).availableQuantity(inventory.getAvailableQuantity()).currentPrice(price.getCurrentPrice()).originalPrice(price.getOriginalPrice()).build();}public CategoryDTO assembleWithProducts(Category category, ListProduct products) {return CategoryDTO.builder().id(category.getId()).name(category.getName()).path(category.getPath()).productCount(products.size()).products(products.stream().map(this::toSimpleProductDTO).collect(Collectors.toList())).build();}private SimpleProductDTO toSimpleProductDTO(Product product) {return SimpleProductDTO.builder().id(product.getId()).name(product.getName()).build();}
}// 专门的查询服务避免循环依赖
Service
public class CategoryQueryService {Autowiredprivate CategoryRepository categoryRepository;Autowiredprivate ProductRepository productRepository;Autowiredprivate ProductDTOAssembler assembler;public CategoryDTO getCategoryWithProducts(Long categoryId) {Category category categoryRepository.findById(categoryId);ListProduct products productRepository.findByCategoryId(categoryId);return assembler.assembleWithProducts(category, products);}
}监控和诊断工具
1. 自定义循环依赖监控
Component
public class CircularDependencyMonitor {private static final Logger logger LoggerFactory.getLogger(CircularDependencyMonitor.class);private final MapString, Long beanCreationTimes new ConcurrentHashMap();private final MapString, SetString dependencyChains new ConcurrentHashMap();EventListenerpublic void onBeanCreationStart(BeanCreationStartEvent event) {String beanName event.getBeanName();beanCreationTimes.put(beanName, System.currentTimeMillis());// 记录依赖链recordDependencyChain(beanName, event.getDependencyChain());}EventListenerpublic void onBeanCreationEnd(BeanCreationEndEvent event) {String beanName event.getBeanName();Long startTime beanCreationTimes.remove(beanName);if (startTime ! null) {long duration System.currentTimeMillis() - startTime;if (duration 1000) { // 超过1秒的Bean创建logger.warn(Bean {} 创建耗时过长: {}ms, 可能存在循环依赖, beanName, duration);// 分析依赖链analyzeDependencyChain(beanName);}}}private void recordDependencyChain(String beanName, SetString chain) {dependencyChains.put(beanName, new HashSet(chain));}private void analyzeDependencyChain(String beanName) {SetString chain dependencyChains.get(beanName);if (chain ! null chain.size() 3) {logger.warn(Bean {} 的依赖链较长: {}, beanName, chain);// 检测是否存在循环if (detectCircularInChain(chain)) {logger.error(检测到循环依赖: {}, chain);}}}private boolean detectCircularInChain(SetString chain) {// 简化的循环检测逻辑return chain.size() ! new HashSet(chain).size();}
}2. Spring Boot Actuator集成
Component
Endpoint(id circular-dependencies)
public class CircularDependencyEndpoint {Autowiredprivate ApplicationContext applicationContext;ReadOperationpublic MapString, Object circularDependencies() {MapString, Object result new HashMap();// 分析所有Bean的依赖关系MapString, SetString dependencyGraph buildDependencyGraph();// 检测循环依赖ListListString cycles detectAllCycles(dependencyGraph);result.put(totalBeans, dependencyGraph.size());result.put(circularDependencies, cycles);result.put(affectedBeans, cycles.stream().flatMap(List::stream).distinct().count());return result;}private MapString, SetString buildDependencyGraph() {MapString, SetString graph new HashMap();if (applicationContext instanceof ConfigurableApplicationContext) {ConfigurableListableBeanFactory beanFactory ((ConfigurableApplicationContext) applicationContext).getBeanFactory();String[] beanNames beanFactory.getBeanDefinitionNames();for (String beanName : beanNames) {try {BeanDefinition bd beanFactory.getBeanDefinition(beanName);SetString dependencies extractDependencies(bd);graph.put(beanName, dependencies);} catch (Exception e) {// 忽略无法分析的Bean}}}return graph;}private ListListString detectAllCycles(MapString, SetString graph) {ListListString cycles new ArrayList();SetString visited new HashSet();for (String node : graph.keySet()) {if (!visited.contains(node)) {ListString path new ArrayList();SetString pathSet new HashSet();findCycles(graph, node, visited, path, pathSet, cycles);}}return cycles;}private void findCycles(MapString, SetString graph, String current,SetString visited, ListString path, SetString pathSet, ListListString cycles) {if (pathSet.contains(current)) {// 找到循环int cycleStart path.indexOf(current);ListString cycle new ArrayList(path.subList(cycleStart, path.size()));cycle.add(current);cycles.add(cycle);return;}if (visited.contains(current)) {return;}visited.add(current);path.add(current);pathSet.add(current);SetString neighbors graph.get(current);if (neighbors ! null) {for (String neighbor : neighbors) {findCycles(graph, neighbor, visited, path, pathSet, cycles);}}path.remove(path.size() - 1);pathSet.remove(current);}private SetString extractDependencies(BeanDefinition beanDefinition) {// 实现依赖提取逻辑SetString dependencies new HashSet();// 提取构造器依赖ConstructorArgumentValues constructorArgs beanDefinition.getConstructorArgumentValues();extractDependenciesFromConstructorArgs(constructorArgs, dependencies);// 提取属性依赖MutablePropertyValues propertyValues beanDefinition.getPropertyValues();extractDependenciesFromPropertyValues(propertyValues, dependencies);return dependencies;}
}3. 性能监控和优化
Component
public class CircularDependencyPerformanceMonitor {private final MeterRegistry meterRegistry;private final Timer.Sample sample;public CircularDependencyPerformanceMonitor(MeterRegistry meterRegistry) {this.meterRegistry meterRegistry;this.sample Timer.start(meterRegistry);}EventListenerpublic void onApplicationReady(ApplicationReadyEvent event) {sample.stop(Timer.builder(spring.context.startup.time).description(Spring context startup time).register(meterRegistry));// 分析启动过程中的循环依赖处理analyzeStartupPerformance();}private void analyzeStartupPerformance() {ApplicationContext context applicationContext;// 统计Bean创建耗时MapString, Long beanCreationTimes getBeanCreationTimes();// 识别耗时最长的BeanString slowestBean beanCreationTimes.entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey).orElse(unknown);Long slowestTime beanCreationTimes.get(slowestBean);// 记录指标Gauge.builder(spring.bean.creation.slowest.time).description(Slowest bean creation time).register(meterRegistry, slowestTime);Counter.builder(spring.circular.dependencies.resolved).description(Number of circular dependencies resolved).register(meterRegistry).increment(countResolvedCircularDependencies());}private MapString, Long getBeanCreationTimes() {// 实现Bean创建时间统计return new HashMap();}private int countResolvedCircularDependencies() {// 统计解决的循环依赖数量return 0;}
}最佳实践总结
1. 设计原则
/*** 避免循环依赖的设计原则*/
public class CircularDependencyBestPractices {/*** 1. 单一职责原则* 每个类应该只有一个明确的职责避免过度耦合*/Servicepublic class UserService {// 只负责用户相关的核心业务逻辑public User createUser(CreateUserRequest request) {// 用户创建逻辑}}/*** 2. 依赖倒置原则* 依赖抽象而不是具体实现*/Servicepublic class OrderService {// 依赖接口而不是具体实现private final UserRepository userRepository;private final NotificationSender notificationSender;public OrderService(UserRepository userRepository, NotificationSender notificationSender) {this.userRepository userRepository;this.notificationSender notificationSender;}}/*** 3. 接口隔离原则* 使用小而专一的接口*/public interface UserValidator {boolean validateUser(User user);}public interface OrderValidator {boolean validateOrder(Order order);}/*** 4. 事件驱动架构* 使用事件解耦服务间的直接依赖*/Servicepublic class EventDrivenUserService {Autowiredprivate ApplicationEventPublisher eventPublisher;public User createUser(CreateUserRequest request) {User user new User(request);user userRepository.save(user);// 发布事件而不是直接调用其他服务eventPublisher.publishEvent(new UserCreatedEvent(user));return user;}}
}2. 代码检查清单
/*** 循环依赖检查清单*/
public class CircularDependencyChecklist {/*** 检查项目* * 1. 构造器注入检查* - 避免构造器循环依赖* - 使用Lazy注解打破循环* * 2. 服务层设计检查* - 服务职责是否单一* - 是否存在相互调用* * 3. 依赖关系检查* - 依赖层次是否清晰* - 是否违反分层架构原则* * 4. 配置检查* - Bean作用域是否合适* - 是否正确使用Lazy* * 5. 测试覆盖* - 是否有集成测试覆盖循环依赖场景* - 是否有性能测试验证启动时间*/public void performChecklist() {checkConstructorDependencies();checkServiceLayerDesign();checkDependencyHierarchy();checkConfiguration();checkTestCoverage();}private void checkConstructorDependencies() {// 检查构造器循环依赖}private void checkServiceLayerDesign() {// 检查服务层设计}private void checkDependencyHierarchy() {// 检查依赖层次}private void checkConfiguration() {// 检查配置}private void checkTestCoverage() {// 检查测试覆盖率}
}结论
Spring通过精妙的三级缓存机制成功解决了单例Bean的循环依赖问题这一设计体现了Spring框架的深度思考和技术实力。理解这一机制不仅有助于我们更好地使用Spring还能帮助我们
关键要点回顾三级缓存的作用
一级缓存存储完全初始化的Bean二级缓存存储早期Bean引用解决循环依赖三级缓存存储Bean工厂处理AOP代理解决原理
在Bean实例化后立即暴露早期引用通过工厂模式延迟决定是否创建代理确保循环依赖中对象引用的一致性限制条件
只能解决单例Bean的setter注入循环依赖无法解决构造器循环依赖无法解决prototype作用域的循环依赖最佳实践
优先使用setter注入而非构造器注入合理使用Lazy注解采用事件驱动架构解耦服务遵循SOLID设计原则实际应用建议
在实际开发中我们应该
预防为主通过良好的架构设计避免循环依赖监控诊断使用工具监控和诊断循环依赖问题性能优化关注循环依赖对启动性能的影响持续改进定期重构代码消除不必要的依赖关系
Spring的循环依赖解决方案是一个经典的工程实践案例它告诉我们面对复杂的技术问题往往需要巧妙的设计和精细的实现。掌握这些知识不仅能帮助我们更好地使用Spring框架还能提升我们的系统设计能力。