最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring解決循環(huán)依賴的方法及三級緩存機制實踐案例

 更新時間:2025年09月20日 12:05:13   作者:塔中妖  
Spring通過三級緩存解決單例Bean循環(huán)依賴,但無法處理構造器、prototype作用域及@Async場景,建議使用setter注入、@Lazy注解和架構優(yōu)化,遵循設計原則避免依賴問題,本文介紹Spring如何解決循環(huán)依賴:深入理解三級緩存機制,感興趣的朋友一起看看吧

Spring如何解決循環(huán)依賴:深入理解三級緩存機制

引言

在我們之前的文章中,我們探討了什么是循環(huán)依賴以及它帶來的問題。作為Java生態(tài)系統(tǒng)中最重要的框架之一,Spring Framework在處理循環(huán)依賴方面有著獨特而精妙的解決方案。今天,讓我們深入了解Spring是如何通過三級緩存機制巧妙地解決循環(huán)依賴問題的。

Spring中的循環(huán)依賴場景

典型的循環(huán)依賴示例

@Component
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
    public void doSomething() {
        System.out.println("ServiceA doing something");
        serviceB.doSomething();
    }
}
@Component
public class ServiceB {
    @Autowired
    private ServiceC serviceC;
    public void doSomething() {
        System.out.println("ServiceB doing something");
        serviceC.doSomething();
    }
}
@Component
public class ServiceC {
    @Autowired
    private ServiceA serviceA;  // 形成循環(huán)依賴:A -> B -> C -> A
    public void doSomething() {
        System.out.println("ServiceC doing something");
        serviceA.doSomething();
    }
}

構造器循環(huán)依賴(Spring無法解決)

@Component
public class ServiceA {
    private final ServiceB serviceB;
    // 構造器注入形成的循環(huán)依賴,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如何解決循環(huán)依賴,首先需要了解Bean的創(chuàng)建過程:

public class SpringBeanLifecycle {
    /**
     * Spring Bean的完整生命周期
     */
    public Object createBean(String beanName, BeanDefinition beanDefinition) {
        // 1. 實例化 - 創(chuàng)建對象實例(調(diào)用構造器)
        Object bean = instantiateBean(beanName, beanDefinition);
        // 2. 屬性填充 - 依賴注入
        populateBean(bean, beanName, beanDefinition);
        // 3. 初始化 - 調(diào)用初始化方法
        initializeBean(bean, beanName);
        return bean;
    }
    private Object instantiateBean(String beanName, BeanDefinition bd) {
        // 通過反射創(chuàng)建實例
        Constructor<?> constructor = bd.getBeanClass().getDeclaredConstructor();
        return constructor.newInstance();
    }
    private void populateBean(Object bean, String beanName, BeanDefinition bd) {
        // 處理@Autowired、@Resource等注解
        // 這里會觸發(fā)依賴Bean的創(chuàng)建
        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) {
        // 調(diào)用初始化回調(diào)方法
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
}

Spring的三級緩存機制

Spring通過三級緩存來解決單例Bean的循環(huán)依賴問題:

public class DefaultSingletonBeanRegistry {
    /** 一級緩存:完成初始化的單例Bean */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    /** 二級緩存:完成實例化但未完成初始化的Bean */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    /** 三級緩存:單例Bean的工廠 */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    /** 正在創(chuàng)建的Bean名稱集合 */
    private final Set<String> singletonsCurrentlyInCreation = 
        Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    /**
     * 獲取單例Bean的核心方法
     */
    protected Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 1. 從一級緩存中獲取完全初始化的Bean
        Object 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) {
                        // 調(diào)用工廠方法創(chuàng)建早期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);
        }
    }
}

循環(huán)依賴解決過程詳解

讓我們通過一個具體的例子來看看Spring是如何解決循環(huán)依賴的:

/**
 * 模擬Spring解決循環(huán)依賴的完整過程
 */
public class CircularDependencyResolver {
    // 三級緩存
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    private Map<String, Object> earlySingletonObjects = new HashMap<>();
    private Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
    private Set<String> singletonsCurrentlyInCreation = new HashSet<>();
    /**
     * 創(chuàng)建Bean的主要方法
     */
    public Object getBean(String beanName) {
        // 先嘗試從緩存中獲取
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }
        // 緩存中沒有,開始創(chuàng)建
        return createBean(beanName);
    }
    private Object createBean(String beanName) {
        // 標記Bean正在創(chuàng)建中
        singletonsCurrentlyInCreation.add(beanName);
        try {
            // 1. 實例化Bean
            Object bean = instantiateBean(beanName);
            // 2. 將Bean工廠放入三級緩存(關鍵步驟)
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, bean));
            // 3. 屬性填充(可能觸發(fā)循環(huán)依賴)
            populateBean(bean, beanName);
            // 4. 初始化Bean
            initializeBean(bean, beanName);
            // 5. 將完成的Bean放入一級緩存
            addSingleton(beanName, bean);
            return bean;
        } finally {
            // 移除創(chuàng)建中標記
            singletonsCurrentlyInCreation.remove(beanName);
        }
    }
    private Object instantiateBean(String beanName) {
        // 模擬通過反射創(chuàng)建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,這里會觸發(fā)ServiceB的創(chuàng)建
            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);
        // 執(zhí)行初始化邏輯
    }
    /**
     * 獲取早期Bean引用(處理AOP代理)
     */
    private Object getEarlyBeanReference(String beanName, Object bean) {
        System.out.println("獲取早期Bean引用: " + beanName);
        // 如果需要AOP代理,在這里創(chuàng)建代理對象
        if (needsProxy(beanName)) {
            return createProxy(bean);
        }
        return bean;
    }
    private boolean needsProxy(String beanName) {
        // 簡化的代理判斷邏輯
        return beanName.contains("service");
    }
    private Object createProxy(Object target) {
        // 簡化的代理創(chuàng)建邏輯
        System.out.println("創(chuàng)建代理對象: " + 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);
    }
}

循環(huán)依賴解決的時序圖

ServiceA創(chuàng)建過程:
1. 實例化ServiceA
2. 將ServiceA工廠放入三級緩存
3. 填充ServiceA屬性,需要ServiceB
   |
   ├─ ServiceB創(chuàng)建過程:
   │  1. 實例化ServiceB  
   │  2. 將ServiceB工廠放入三級緩存
   │  3. 填充ServiceB屬性,需要ServiceA
   │  4. 從三級緩存獲取ServiceA早期引用
   │  5. 完成ServiceB初始化,放入一級緩存
   │
4. 獲得ServiceB實例,完成ServiceA屬性填充
5. 完成ServiceA初始化,放入一級緩存

為什么需要三級緩存?

只有一級緩存的問題

public class SingleCacheExample {
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    public Object getBean(String beanName) {
        Object bean = singletonObjects.get(beanName);
        if (bean != null) {
            return bean;
        }
        // 創(chuàng)建Bean
        bean = createBean(beanName);
        singletonObjects.put(beanName, bean);
        return bean;
    }
    // 問題:在Bean完全創(chuàng)建完成之前,其他Bean無法獲取到它的引用
    // 導致循環(huán)依賴無法解決
}

只有二級緩存的問題

public class TwoCacheExample {
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    private Map<String, Object> earlySingletonObjects = new HashMap<>();
    // 問題:無法處理AOP代理的情況
    // 如果Bean需要被代理,早期引用和最終對象可能不是同一個實例
}

三級緩存的優(yōu)勢

/**
 * 三級緩存解決的問題:
 * 1. 一級緩存:存儲完全初始化的Bean
 * 2. 二級緩存:存儲早期Bean引用,解決循環(huán)依賴
 * 3. 三級緩存:存儲Bean工廠,延遲決定是否需要代理
 */
public class ThreeCacheAdvantages {
    /**
     * 三級緩存的關鍵作用:
     * 1. 延遲代理對象的創(chuàng)建
     * 2. 確保循環(huán)依賴中代理對象的一致性
     * 3. 避免不必要的代理對象創(chuàng)建
     */
    private Object getEarlyBeanReference(String beanName, Object bean) {
        // 只有在真正需要早期引用時才決定是否創(chuàng)建代理
        if (hasCircularDependency(beanName)) {
            if (needsProxy(beanName)) {
                return createProxy(bean);
            }
        }
        return bean;
    }
}

AOP與循環(huán)依賴

Spring AOP為循環(huán)依賴的解決增加了復雜性:

@Component
@Service
public class UserService {
    @Autowired
    private OrderService orderService;
    @Transactional  // 這個注解會導致創(chuàng)建AOP代理
    public void createUser(User user) {
        // 業(yè)務邏輯
        orderService.createDefaultOrder(user);
    }
}
@Component
@Service  
public class OrderService {
    @Autowired
    private UserService userService;
    @Transactional
    public void createDefaultOrder(User user) {
        // 業(yè)務邏輯
        userService.validateUser(user);
    }
}

AOP代理處理過程:

public class AopCircularDependencyHandler {
    /**
     * 處理AOP代理的循環(huán)依賴
     */
    public Object resolveAopCircularDependency(String beanName, Object bean) {
        // 1. 檢查是否需要創(chuàng)建代理
        if (shouldCreateProxy(bean)) {
            // 2. 創(chuàng)建代理對象
            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動態(tài)代理創(chuàng)建代理對象
        ProxyFactory proxyFactory = new ProxyFactory(target);
        // 添加事務攔截器
        proxyFactory.addAdvice(new TransactionInterceptor());
        return proxyFactory.getProxy();
    }
}

Spring無法解決的循環(huán)依賴場景

1. 構造器循環(huán)依賴

@Component
public class ServiceA {
    private final ServiceB serviceB;
    // Spring無法解決構造器循環(huán)依賴
    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作用域的循環(huán)依賴

@Component
@Scope("prototype")
public class PrototypeServiceA {
    @Autowired
    private PrototypeServiceB serviceB;
}
@Component
@Scope("prototype")
public class PrototypeServiceB {
    @Autowired
    private PrototypeServiceA serviceA;
}
// prototype作用域的Bean每次都會創(chuàng)建新實例,無法使用緩存解決循環(huán)依賴

3. @Async注解的特殊情況

@Component
public class AsyncServiceA {
    @Autowired
    private AsyncServiceB serviceB;
    @Async
    public void doAsync() {
        serviceB.doSomething();
    }
}
@Component
public class AsyncServiceB {
    @Autowired
    private AsyncServiceA serviceA;
    public void doSomething() {
        serviceA.doAsync();
    }
}
// 在某些情況下,@Async可能導致循環(huán)依賴解決失敗

循環(huán)依賴的解決方案

1. 使用@Lazy注解

@Component
public class ServiceA {
    private final ServiceB serviceB;
    // 使用@Lazy延遲注入,打破循環(huán)依賴
    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注入替代構造器注入
    @Autowired
    public void setServiceB(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}
@Component
public class ServiceB {
    private ServiceA serviceA;
    @Autowired
    public void setServiceA(ServiceA serviceA) {
        this.serviceA = serviceA;
    }
}

3. 使用@PostConstruct

@Component
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
    private ServiceA selfReference;
    @PostConstruct
    public void init() {
        // 在初始化階段設置自引用
        this.selfReference = this;
    }
}

4. 重新設計架構

// 原始設計:循環(huán)依賴
@Component
public class UserService {
    @Autowired
    private OrderService orderService;
    public void processUser(User user) {
        orderService.processOrder(user.getOrders());
    }
}
@Component
public class OrderService {
    @Autowired
    private UserService userService;
    public void processOrder(List<Order> 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 {
    @Autowired
    private ValidationService validationService;
    public void processUser(User user) {
        validationService.validateUser(user);
        // 處理用戶邏輯
    }
}
@Component
public class OrderService {
    @Autowired
    private ValidationService validationService;
    public void processOrder(Order order) {
        validationService.validateOrder(order);
        // 處理訂單邏輯
    }
}

循環(huán)依賴檢測和調(diào)試

1. 啟用循環(huán)依賴檢測

@Configuration
@EnableAutoConfiguration
public class AppConfig {
    @Bean
    public static BeanFactoryPostProcessor circularDependencyDetector() {
        return new BeanFactoryPostProcessor() {
            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                if (beanFactory instanceof DefaultListableBeanFactory) {
                    DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;
                    factory.setAllowCircularReferences(false); // 禁用循環(huán)依賴
                }
            }
        };
    }
}

2. 自定義循環(huán)依賴檢測器

@Component
public class CircularDependencyDetector implements BeanPostProcessor {
    private final Set<String> beansInCreation = new HashSet<>();
    private final Map<String, Set<String>> dependencyGraph = new HashMap<>();
    @Override
    public 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的依賴關系
        // 構建依賴圖,檢測環(huán)路
    }
}

3. 循環(huán)依賴調(diào)試工具

@Component
public class CircularDependencyDebugger {
    private static final Logger logger = LoggerFactory.getLogger(CircularDependencyDebugger.class);
    @EventListener
    public 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);
                // 分析依賴關系
                Set<String> dependencies = extractDependencies(beanDefinition);
                logger.info("Bean {} depends on: {}", beanName, dependencies);
            } catch (Exception e) {
                logger.warn("Failed to analyze dependencies for bean: {}", beanName, e);
            }
        }
    }
    private Set<String> extractDependencies(BeanDefinition beanDefinition) {
        Set<String> 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. 內(nèi)存開銷:三個Map需要額外的內(nèi)存
        // 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. 優(yōu)化建議

@Configuration
public class CircularDependencyOptimization {
    /**
     * 優(yōu)化循環(huán)依賴處理的配置
     */
    @Bean
    public static BeanFactoryPostProcessor optimizeCircularDependency() {
        return beanFactory -> {
            if (beanFactory instanceof DefaultListableBeanFactory) {
                DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;
                // 1. 預分析Bean依賴關系,提前發(fā)現(xiàn)循環(huán)依賴
                preAnalyzeDependencies(factory);
                // 2. 優(yōu)化緩存大小
                optimizeCacheSize(factory);
                // 3. 啟用并發(fā)優(yōu)化
                enableConcurrentOptimization(factory);
            }
        };
    }
```java
    private static void preAnalyzeDependencies(DefaultListableBeanFactory factory) {
        String[] beanNames = factory.getBeanDefinitionNames();
        Map<String, Set<String>> dependencyGraph = new HashMap<>();
        // 構建依賴圖
        for (String beanName : beanNames) {
            BeanDefinition bd = factory.getBeanDefinition(beanName);
            Set<String> dependencies = extractBeanDependencies(bd);
            dependencyGraph.put(beanName, dependencies);
        }
        // 檢測循環(huán)依賴
        detectCycles(dependencyGraph);
    }
    private static void detectCycles(Map<String, Set<String>> graph) {
        Set<String> visited = new HashSet<>();
        Set<String> recursionStack = new HashSet<>();
        for (String node : graph.keySet()) {
            if (hasCycle(graph, node, visited, recursionStack)) {
                System.out.println("檢測到循環(huán)依賴,涉及Bean: " + node);
            }
        }
    }
    private static boolean hasCycle(Map<String, Set<String>> graph, String node, 
                                   Set<String> visited, Set<String> recursionStack) {
        if (recursionStack.contains(node)) {
            return true; // 發(fā)現(xiàn)環(huán)路
        }
        if (visited.contains(node)) {
            return false; // 已經(jīng)訪問過,無環(huán)路
        }
        visited.add(node);
        recursionStack.add(node);
        Set<String> 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) {
        // 根據(jù)Bean數(shù)量優(yōu)化緩存初始容量
        int beanCount = factory.getBeanDefinitionCount();
        int optimalCacheSize = Math.max(16, beanCount / 4);
        // 這里可以通過反射設置緩存的初始容量
        // 實際實現(xiàn)中需要訪問私有字段
    }
    private static void enableConcurrentOptimization(DefaultListableBeanFactory factory) {
        // 啟用并發(fā)創(chuàng)建Bean的優(yōu)化
        factory.setAllowEagerClassLoading(true);
        factory.setAllowRawInjectionDespiteWrapping(true);
    }
}

實際應用案例

案例1:微服務中的循環(huán)依賴

/**
 * 微服務架構中常見的循環(huán)依賴場景
 */
@Service
public class UserService {
    @Autowired
    private OrderService orderService;
    @Autowired
    private NotificationService notificationService;
    @Transactional
    public User createUser(CreateUserRequest request) {
        User user = new User(request);
        user = userRepository.save(user);
        // 創(chuàng)建用戶后,創(chuàng)建默認訂單
        orderService.createWelcomeOrder(user);
        // 發(fā)送歡迎通知
        notificationService.sendWelcomeNotification(user);
        return user;
    }
}
@Service
public class OrderService {
    @Autowired
    private UserService userService; // 循環(huán)依賴
    @Autowired
    private PaymentService paymentService;
    @Transactional
    public Order createWelcomeOrder(User user) {
        Order order = new Order(user, getWelcomeProducts());
        order = orderRepository.save(order);
        // 更新用戶的訂單統(tǒng)計
        userService.updateOrderStatistics(user.getId());
        return order;
    }
}
@Service
public class NotificationService {
    @Autowired
    private UserService userService; // 另一個循環(huán)依賴
    public void sendWelcomeNotification(User user) {
        // 獲取用戶偏好設置
        UserPreference preference = userService.getUserPreference(user.getId());
        if (preference.isEmailEnabled()) {
            emailService.sendWelcomeEmail(user);
        }
        if (preference.isSmsEnabled()) {
            smsService.sendWelcomeSms(user);
        }
    }
}

解決方案:

/**
 * 重構后的解決方案:使用事件驅(qū)動架構
 */
@Service
public class UserService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Transactional
    public User createUser(CreateUserRequest request) {
        User user = new User(request);
        user = userRepository.save(user);
        // 發(fā)布用戶創(chuàng)建事件,而不是直接調(diào)用其他服務
        eventPublisher.publishEvent(new UserCreatedEvent(user));
        return user;
    }
    public void updateOrderStatistics(Long userId) {
        // 更新用戶訂單統(tǒng)計
        User user = userRepository.findById(userId);
        user.incrementOrderCount();
        userRepository.save(user);
    }
    public UserPreference getUserPreference(Long userId) {
        return userPreferenceRepository.findByUserId(userId);
    }
}
@Service
public class OrderService {
    // 移除對UserService的直接依賴
    @EventListener
    @Async
    public void handleUserCreated(UserCreatedEvent event) {
        createWelcomeOrder(event.getUser());
    }
    @Transactional
    public Order createWelcomeOrder(User user) {
        Order order = new Order(user, getWelcomeProducts());
        order = orderRepository.save(order);
        // 發(fā)布訂單創(chuàng)建事件
        eventPublisher.publishEvent(new OrderCreatedEvent(order));
        return order;
    }
}
@Service
public class NotificationService {
    // 移除對UserService的直接依賴
    @Autowired
    private UserPreferenceRepository userPreferenceRepository;
    @EventListener
    @Async
    public void handleUserCreated(UserCreatedEvent event) {
        sendWelcomeNotification(event.getUser());
    }
    public void sendWelcomeNotification(User user) {
        // 直接查詢用戶偏好,避免循環(huán)依賴
        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:復雜的業(yè)務場景循環(huán)依賴

/**
 * 電商系統(tǒng)中的復雜循環(huán)依賴場景
 */
@Service
public class ProductService {
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private 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 {
    @Autowired
    private ProductService productService; // 循環(huán)依賴
    public Category getCategoryWithProducts(Long categoryId) {
        Category category = categoryRepository.findById(categoryId);
        // 獲取分類下的熱門產(chǎn)品
        List<ProductDTO> hotProducts = productService.getHotProductsByCategory(categoryId);
        category.setHotProducts(hotProducts);
        return category;
    }
}
@Service
public class InventoryService {
    @Autowired
    private ProductService productService; // 循環(huán)依賴
    public Inventory getInventoryWithProductInfo(Long productId) {
        Inventory inventory = inventoryRepository.findByProductId(productId);
        // 獲取產(chǎn)品基本信息用于庫存展示
        ProductDTO productInfo = productService.getBasicProductInfo(productId);
        inventory.setProductInfo(productInfo);
        return inventory;
    }
}

解決方案:使用Repository模式和DTO組裝器

/**
 * 重構后的解決方案:分離數(shù)據(jù)訪問和業(yè)務邏輯
 */
@Service
public class ProductQueryService {
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private CategoryRepository categoryRepository;
    @Autowired
    private InventoryRepository inventoryRepository;
    @Autowired
    private PriceRepository priceRepository;
    @Autowired
    private ProductDTOAssembler productDTOAssembler;
    /**
     * 獲取完整的產(chǎn)品信息,避免循環(huán)依賴
     */
    public ProductDTO getProductDetails(Long productId) {
        // 1. 獲取基礎數(shù)據(jù)
        Product product = productRepository.findById(productId);
        Category category = categoryRepository.findById(product.getCategoryId());
        Inventory inventory = inventoryRepository.findByProductId(productId);
        Price price = priceRepository.findByProductId(productId);
        // 2. 組裝DTO
        return 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, List<Product> 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();
    }
}
// 專門的查詢服務,避免循環(huán)依賴
@Service
public class CategoryQueryService {
    @Autowired
    private CategoryRepository categoryRepository;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ProductDTOAssembler assembler;
    public CategoryDTO getCategoryWithProducts(Long categoryId) {
        Category category = categoryRepository.findById(categoryId);
        List<Product> products = productRepository.findByCategoryId(categoryId);
        return assembler.assembleWithProducts(category, products);
    }
}

監(jiān)控和診斷工具

1. 自定義循環(huán)依賴監(jiān)控

@Component
public class CircularDependencyMonitor {
    private static final Logger logger = LoggerFactory.getLogger(CircularDependencyMonitor.class);
    private final Map<String, Long> beanCreationTimes = new ConcurrentHashMap<>();
    private final Map<String, Set<String>> dependencyChains = new ConcurrentHashMap<>();
    @EventListener
    public void onBeanCreationStart(BeanCreationStartEvent event) {
        String beanName = event.getBeanName();
        beanCreationTimes.put(beanName, System.currentTimeMillis());
        // 記錄依賴鏈
        recordDependencyChain(beanName, event.getDependencyChain());
    }
    @EventListener
    public 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創(chuàng)建
                logger.warn("Bean {} 創(chuàng)建耗時過長: {}ms, 可能存在循環(huán)依賴", beanName, duration);
                // 分析依賴鏈
                analyzeDependencyChain(beanName);
            }
        }
    }
    private void recordDependencyChain(String beanName, Set<String> chain) {
        dependencyChains.put(beanName, new HashSet<>(chain));
    }
    private void analyzeDependencyChain(String beanName) {
        Set<String> chain = dependencyChains.get(beanName);
        if (chain != null && chain.size() > 3) {
            logger.warn("Bean {} 的依賴鏈較長: {}", beanName, chain);
            // 檢測是否存在循環(huán)
            if (detectCircularInChain(chain)) {
                logger.error("檢測到循環(huán)依賴: {}", chain);
            }
        }
    }
    private boolean detectCircularInChain(Set<String> chain) {
        // 簡化的循環(huán)檢測邏輯
        return chain.size() != new HashSet<>(chain).size();
    }
}

2. Spring Boot Actuator集成

@Component
@Endpoint(id = "circular-dependencies")
public class CircularDependencyEndpoint {
    @Autowired
    private ApplicationContext applicationContext;
    @ReadOperation
    public Map<String, Object> circularDependencies() {
        Map<String, Object> result = new HashMap<>();
        // 分析所有Bean的依賴關系
        Map<String, Set<String>> dependencyGraph = buildDependencyGraph();
        // 檢測循環(huán)依賴
        List<List<String>> 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 Map<String, Set<String>> buildDependencyGraph() {
        Map<String, Set<String>> 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);
                    Set<String> dependencies = extractDependencies(bd);
                    graph.put(beanName, dependencies);
                } catch (Exception e) {
                    // 忽略無法分析的Bean
                }
            }
        }
        return graph;
    }
    private List<List<String>> detectAllCycles(Map<String, Set<String>> graph) {
        List<List<String>> cycles = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        for (String node : graph.keySet()) {
            if (!visited.contains(node)) {
                List<String> path = new ArrayList<>();
                Set<String> pathSet = new HashSet<>();
                findCycles(graph, node, visited, path, pathSet, cycles);
            }
        }
        return cycles;
    }
    private void findCycles(Map<String, Set<String>> graph, String current,
                           Set<String> visited, List<String> path, 
                           Set<String> pathSet, List<List<String>> cycles) {
        if (pathSet.contains(current)) {
            // 找到循環(huán)
            int cycleStart = path.indexOf(current);
            List<String> 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);
        Set<String> 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 Set<String> extractDependencies(BeanDefinition beanDefinition) {
        // 實現(xiàn)依賴提取邏輯
        Set<String> dependencies = new HashSet<>();
        // 提取構造器依賴
        ConstructorArgumentValues constructorArgs = beanDefinition.getConstructorArgumentValues();
        extractDependenciesFromConstructorArgs(constructorArgs, dependencies);
        // 提取屬性依賴
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        extractDependenciesFromPropertyValues(propertyValues, dependencies);
        return dependencies;
    }
}

3. 性能監(jiān)控和優(yōu)化

@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);
    }
    @EventListener
    public void onApplicationReady(ApplicationReadyEvent event) {
        sample.stop(Timer.builder("spring.context.startup.time")
                .description("Spring context startup time")
                .register(meterRegistry));
        // 分析啟動過程中的循環(huán)依賴處理
        analyzeStartupPerformance();
    }
    private void analyzeStartupPerformance() {
        ApplicationContext context = applicationContext;
        // 統(tǒng)計Bean創(chuàng)建耗時
        Map<String, Long> beanCreationTimes = getBeanCreationTimes();
        // 識別耗時最長的Bean
        String 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 Map<String, Long> getBeanCreationTimes() {
        // 實現(xiàn)Bean創(chuàng)建時間統(tǒng)計
        return new HashMap<>();
    }
    private int countResolvedCircularDependencies() {
        // 統(tǒng)計解決的循環(huán)依賴數(shù)量
        return 0;
    }
}

最佳實踐總結(jié)

1. 設計原則

/**
 * 避免循環(huán)依賴的設計原則
 */
public class CircularDependencyBestPractices {
    /**
     * 1. 單一職責原則
     * 每個類應該只有一個明確的職責,避免過度耦合
     */
    @Service
    public class UserService {
        // 只負責用戶相關的核心業(yè)務邏輯
        public User createUser(CreateUserRequest request) {
            // 用戶創(chuàng)建邏輯
        }
    }
    /**
     * 2. 依賴倒置原則
     * 依賴抽象而不是具體實現(xiàn)
     */
    @Service
    public class OrderService {
        // 依賴接口而不是具體實現(xiàn)
        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. 事件驅(qū)動架構
     * 使用事件解耦服務間的直接依賴
     */
    @Service
    public class EventDrivenUserService {
        @Autowired
        private ApplicationEventPublisher eventPublisher;
        public User createUser(CreateUserRequest request) {
            User user = new User(request);
            user = userRepository.save(user);
            // 發(fā)布事件而不是直接調(diào)用其他服務
            eventPublisher.publishEvent(new UserCreatedEvent(user));
            return user;
        }
    }
}

2. 代碼檢查清單

/**
 * 循環(huán)依賴檢查清單
 */
public class CircularDependencyChecklist {
    /**
     * 檢查項目:
     * 
     * 1. 構造器注入檢查
     * - 避免構造器循環(huán)依賴
     * - 使用@Lazy注解打破循環(huán)
     * 
     * 2. 服務層設計檢查
     * - 服務職責是否單一
     * - 是否存在相互調(diào)用
     * 
     * 3. 依賴關系檢查
     * - 依賴層次是否清晰
     * - 是否違反分層架構原則
     * 
     * 4. 配置檢查
     * - Bean作用域是否合適
     * - 是否正確使用@Lazy
     * 
     * 5. 測試覆蓋
     * - 是否有集成測試覆蓋循環(huán)依賴場景
     * - 是否有性能測試驗證啟動時間
     */
    public void performChecklist() {
        checkConstructorDependencies();
        checkServiceLayerDesign();
        checkDependencyHierarchy();
        checkConfiguration();
        checkTestCoverage();
    }
    private void checkConstructorDependencies() {
        // 檢查構造器循環(huán)依賴
    }
    private void checkServiceLayerDesign() {
        // 檢查服務層設計
    }
    private void checkDependencyHierarchy() {
        // 檢查依賴層次
    }
    private void checkConfiguration() {
        // 檢查配置
    }
    private void checkTestCoverage() {
        // 檢查測試覆蓋率
    }
}

結(jié)論

Spring通過精妙的三級緩存機制成功解決了單例Bean的循環(huán)依賴問題,這一設計體現(xiàn)了Spring框架的深度思考和技術實力。理解這一機制不僅有助于我們更好地使用Spring,還能幫助我們:

關鍵要點回顧

  • 三級緩存的作用
    • 一級緩存:存儲完全初始化的Bean
    • 二級緩存:存儲早期Bean引用,解決循環(huán)依賴
    • 三級緩存:存儲Bean工廠,處理AOP代理
  • 解決原理
    • 在Bean實例化后立即暴露早期引用
    • 通過工廠模式延遲決定是否創(chuàng)建代理
    • 確保循環(huán)依賴中對象引用的一致性
  • 限制條件
    • 只能解決單例Bean的setter注入循環(huán)依賴
    • 無法解決構造器循環(huán)依賴
    • 無法解決prototype作用域的循環(huán)依賴
  • 最佳實踐
    • 優(yōu)先使用setter注入而非構造器注入
    • 合理使用@Lazy注解
    • 采用事件驅(qū)動架構解耦服務
    • 遵循SOLID設計原則

實際應用建議

在實際開發(fā)中,我們應該:

  1. 預防為主:通過良好的架構設計避免循環(huán)依賴
  2. 監(jiān)控診斷:使用工具監(jiān)控和診斷循環(huán)依賴問題
  3. 性能優(yōu)化:關注循環(huán)依賴對啟動性能的影響
  4. 持續(xù)改進:定期重構代碼,消除不必要的依賴關系

Spring的循環(huán)依賴解決方案是一個經(jīng)典的工程實踐案例,它告訴我們:面對復雜的技術問題,往往需要巧妙的設計和精細的實現(xiàn)。掌握這些知識不僅能幫助我們更好地使用Spring框架,還能提升我們的系統(tǒng)設計能力。

到此這篇關于Spring如何解決循環(huán)依賴:深入理解三級緩存機制的文章就介紹到這了,更多相關Spring循環(huán)依賴三級緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java自定義日志輸出文件(log4j日志文件輸出多個自定義日志文件)

    java自定義日志輸出文件(log4j日志文件輸出多個自定義日志文件)

    打印日志的在程序中是必不可少的,如果需要將不同的日志打印到不同的地方,則需要定義不同的Appender,然后定義每一個Appender的日志級別、打印形式和日志的輸出路徑,下面看一個示例吧
    2014-01-01
  • Spring Security OAuth2.0登出的實現(xiàn)

    Spring Security OAuth2.0登出的實現(xiàn)

    本文主要介紹了Spring Security OAuth2.0登出的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-03-03
  • SpringBootAdmin+actuator實現(xiàn)服務監(jiān)控

    SpringBootAdmin+actuator實現(xiàn)服務監(jiān)控

    這篇文章主要為大家詳細介紹了SpringBootAdmin+actuator實現(xiàn)服務監(jiān)控,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Mybatis中typeAliases的使用

    Mybatis中typeAliases的使用

    這篇文章主要介紹了Mybatis中typeAliases的使用,需要的朋友可以參考下
    2017-08-08
  • Java中泛型學習之細節(jié)篇

    Java中泛型學習之細節(jié)篇

    泛型在java中有很重要的地位,在面向?qū)ο缶幊碳案鞣N設計模式中有非常廣泛的應用,下面這篇文章主要給大家介紹了關于Java中泛型細節(jié)的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-02-02
  • MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    大家都知道Hibernate 是全自動的數(shù)據(jù)庫持久層框架,它可以通過實體來映射數(shù)據(jù)庫,通過設置一對多、多對一、一對一、多對多的關聯(lián)來實現(xiàn)聯(lián)合查詢,接下來通過本文給大家介紹MyBatis?多表聯(lián)合查詢及優(yōu)化,需要的朋友可以參考下
    2022-08-08
  • Springboot整合Netty實現(xiàn)RPC服務器的示例代碼

    Springboot整合Netty實現(xiàn)RPC服務器的示例代碼

    這篇文章主要介紹了Springboot整合Netty實現(xiàn)RPC服務器的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • 關于SpringBoot配置文件加載位置的優(yōu)先級

    關于SpringBoot配置文件加載位置的優(yōu)先級

    這篇文章主要介紹了關于SpringBoot配置文件加載位置的優(yōu)先級,我們也可以通過spring.config.location來改變默認的配置文件位置,項目打包好后,我們可以通過命令行的方式在啟動時指定配置文件的位置,需要的朋友可以參考下
    2023-10-10
  • SpringBoot版本沖突導致NoSuchFieldError的解決方案

    SpringBoot版本沖突導致NoSuchFieldError的解決方案

    在Spring Boot多模塊項目中,若父模塊與子模塊引用不同版本的Spring Boot依賴(例如父模塊使用2.7.3,子模塊使用3.2.1),可能導致運行時出現(xiàn)NoSuchFieldError,所以本文給大家介紹了SpringBoot版本沖突導致NoSuchFieldError的解決方案,需要的朋友可以參考下
    2025-05-05
  • 關于后綴表達式的java實現(xiàn)過程

    關于后綴表達式的java實現(xiàn)過程

    這篇文章主要介紹了關于后綴表達式的java實現(xiàn)過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評論

开鲁县| 灵川县| 雷波县| 方正县| 原平市| 左云县| 双辽市| 静乐县| 台北县| 晋城| 丽水市| 敦化市| 乌拉特后旗| 柞水县| 宜宾市| 新乡市| 西丰县| 永平县| 湖南省| 乌兰浩特市| 新和县| 利津县| 辉南县| 甘德县| 井研县| 凤阳县| 伊宁市| 新津县| 彩票| 桃江县| 文化| 余干县| 镇宁| 汝城县| 华阴市| 卢湾区| 来宾市| 西藏| 靖安县| 昌黎县| 南通市|