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

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

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

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

引言

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

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

典型的循環(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();
    }
}

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

@Component
public class ServiceA {
    private final ServiceB serviceB;
    // 構(gòu)造器注入形成的循環(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. 實(shí)例化 - 創(chuàng)建對(duì)象實(shí)例(調(diào)用構(gòu)造器)
        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)建實(shí)例
        Constructor<?> constructor = bd.getBeanClass().getDeclaredConstructor();
        return constructor.newInstance();
    }
    private void populateBean(Object bean, String beanName, BeanDefinition bd) {
        // 處理@Autowired、@Resource等注解
        // 這里會(huì)觸發(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的三級(jí)緩存機(jī)制

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

public class DefaultSingletonBeanRegistry {
    /** 一級(jí)緩存:完成初始化的單例Bean */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    /** 二級(jí)緩存:完成實(shí)例化但未完成初始化的Bean */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    /** 三級(jí)緩存:?jiǎn)卫鼴ean的工廠 */
    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. 從一級(jí)緩存中獲取完全初始化的Bean
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 2. 從二級(jí)緩存中獲取早期Bean引用
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    // 3. 從三級(jí)緩存中獲取Bean工廠
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 調(diào)用工廠方法創(chuàng)建早期Bean引用
                        singletonObject = singletonFactory.getObject();
                        // 將早期Bean引用放入二級(jí)緩存
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 從三級(jí)緩存中移除
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    /**
     * 添加單例Bean工廠到三級(jí)緩存
     */
    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添加到一級(jí)緩存
     */
    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)依賴解決過程詳解

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

/**
 * 模擬Spring解決循環(huán)依賴的完整過程
 */
public class CircularDependencyResolver {
    // 三級(jí)緩存
    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) {
        // 標(biāo)記Bean正在創(chuàng)建中
        singletonsCurrentlyInCreation.add(beanName);
        try {
            // 1. 實(shí)例化Bean
            Object bean = instantiateBean(beanName);
            // 2. 將Bean工廠放入三級(jí)緩存(關(guān)鍵步驟)
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, bean));
            // 3. 屬性填充(可能觸發(fā)循環(huán)依賴)
            populateBean(bean, beanName);
            // 4. 初始化Bean
            initializeBean(bean, beanName);
            // 5. 將完成的Bean放入一級(jí)緩存
            addSingleton(beanName, bean);
            return bean;
        } finally {
            // 移除創(chuàng)建中標(biāo)記
            singletonsCurrentlyInCreation.remove(beanName);
        }
    }
    private Object instantiateBean(String beanName) {
        // 模擬通過反射創(chuàng)建Bean實(shí)例
        System.out.println("實(shí)例化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,這里會(huì)觸發(fā)ServiceB的創(chuàng)建
            Object serviceB = getBean("serviceB");
            serviceA.setServiceB((ServiceB) serviceB);
        } else if (bean instanceof ServiceB) {
            ServiceB serviceB = (ServiceB) bean;
            // 注入ServiceA,這里會(huì)從緩存中獲取早期引用
            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)建代理對(duì)象
        if (needsProxy(beanName)) {
            return createProxy(bean);
        }
        return bean;
    }
    private boolean needsProxy(String beanName) {
        // 簡(jiǎn)化的代理判斷邏輯
        return beanName.contains("service");
    }
    private Object createProxy(Object target) {
        // 簡(jiǎn)化的代理創(chuàng)建邏輯
        System.out.println("創(chuàng)建代理對(duì)象: " + target.getClass().getSimpleName());
        return target; // 實(shí)際應(yīng)該返回代理對(duì)象
    }
    // 其他輔助方法...
    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)依賴解決的時(shí)序圖

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

為什么需要三級(jí)緩存?

只有一級(jí)緩存的問題

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無法獲取到它的引用
    // 導(dǎo)致循環(huán)依賴無法解決
}

只有二級(jí)緩存的問題

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

三級(jí)緩存的優(yōu)勢(shì)

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

AOP與循環(huán)依賴

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

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

AOP代理處理過程:

public class AopCircularDependencyHandler {
    /**
     * 處理AOP代理的循環(huán)依賴
     */
    public Object resolveAopCircularDependency(String beanName, Object bean) {
        // 1. 檢查是否需要?jiǎng)?chuàng)建代理
        if (shouldCreateProxy(bean)) {
            // 2. 創(chuàng)建代理對(duì)象
            Object proxy = createAopProxy(bean);
            // 3. 確保早期引用和最終對(duì)象的一致性
            ensureProxyConsistency(beanName, bean, proxy);
            return proxy;
        }
        return bean;
    }
    private boolean shouldCreateProxy(Object bean) {
        // 檢查是否有@Transactional、@Async等注解
        Class<?> beanClass = bean.getClass();
        // 檢查類級(jí)別注解
        if (beanClass.isAnnotationPresent(Transactional.class) ||
            beanClass.isAnnotationPresent(Async.class)) {
            return true;
        }
        // 檢查方法級(jí)別注解
        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動(dòng)態(tài)代理創(chuàng)建代理對(duì)象
        ProxyFactory proxyFactory = new ProxyFactory(target);
        // 添加事務(wù)攔截器
        proxyFactory.addAdvice(new TransactionInterceptor());
        return proxyFactory.getProxy();
    }
}

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

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

@Component
public class ServiceA {
    private final ServiceB serviceB;
    // Spring無法解決構(gòu)造器循環(huán)依賴
    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}
@Component
public class ServiceB {
    private final ServiceA serviceA;
    public ServiceB(ServiceA serviceA) {
        this.serviceA = serviceA;
    }
}
// 啟動(dòng)時(shí)會(huì)拋出異常:
// 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每次都會(huì)創(chuàng)建新實(shí)例,無法使用緩存解決循環(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可能導(dǎo)致循環(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注入替代構(gòu)造器注入

@Component
public class ServiceA {
    private ServiceB serviceB;
    // 使用Setter注入替代構(gòu)造器注入
    @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() {
        // 在初始化階段設(shè)置自引用
        this.selfReference = this;
    }
}

4. 重新設(shè)計(jì)架構(gòu)

// 原始設(shè)計(jì):循環(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());
        }
    }
}
// 重構(gòu)后:提取公共服務(wù)
@Component
public class ValidationService {
    public void validateUser(User user) {
        // 用戶驗(yàn)證邏輯
    }
    public void validateOrder(Order order) {
        // 訂單驗(yàn)證邏輯
    }
}
@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)依賴檢測(cè)和調(diào)試

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

@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)依賴檢測(cè)器

@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);
        // 分析依賴關(guān)系
        analyzeDependencies(beanName);
        beansInCreation.remove(beanName);
    }
    private void analyzeDependencies(String beanName) {
        // 通過反射分析Bean的依賴關(guān)系
        // 構(gòu)建依賴圖,檢測(cè)環(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的依賴關(guān)系
        analyzeBeanDependencies(context);
    }
    private void analyzeBeanDependencies(ApplicationContext context) {
        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            try {
                BeanDefinition beanDefinition = 
                    ((ConfigurableApplicationContext) context)
                        .getBeanFactory()
                        .getBeanDefinition(beanName);
                // 分析依賴關(guān)系
                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<>();
        // 提取構(gòu)造器依賴
        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. 三級(jí)緩存的性能影響

public class CachePerformanceAnalysis {
    /**
     * 分析三級(jí)緩存對(duì)性能的影響
     */
    public void analyzePerformance() {
        // 1. 內(nèi)存開銷:三個(gè)Map需要額外的內(nèi)存
        // 2. 查找開銷:需要依次查找三個(gè)緩存
        // 3. 同步開銷:緩存操作需要同步
        long startTime = System.nanoTime();
        // 模擬緩存查找
        Object bean = getSingletonFromCache("testBean");
        long endTime = System.nanoTime();
        long duration = endTime - startTime;
        System.out.println("緩存查找耗時(shí): " + duration + " 納秒");
    }
    private Object getSingletonFromCache(String beanName) {
        // 三級(jí)緩存查找的性能開銷
        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. 預(yù)分析Bean依賴關(guān)系,提前發(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<>();
        // 構(gòu)建依賴圖
        for (String beanName : beanNames) {
            BeanDefinition bd = factory.getBeanDefinition(beanName);
            Set<String> dependencies = extractBeanDependencies(bd);
            dependencyGraph.put(beanName, dependencies);
        }
        // 檢測(cè)循環(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("檢測(cè)到循環(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ù)量?jī)?yōu)化緩存初始容量
        int beanCount = factory.getBeanDefinitionCount();
        int optimalCacheSize = Math.max(16, beanCount / 4);
        // 這里可以通過反射設(shè)置緩存的初始容量
        // 實(shí)際實(shí)現(xiàn)中需要訪問私有字段
    }
    private static void enableConcurrentOptimization(DefaultListableBeanFactory factory) {
        // 啟用并發(fā)創(chuàng)建Bean的優(yōu)化
        factory.setAllowEagerClassLoading(true);
        factory.setAllowRawInjectionDespiteWrapping(true);
    }
}

實(shí)際應(yīng)用案例

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

/**
 * 微服務(wù)架構(gòu)中常見的循環(huán)依賴場(chǎng)景
 */
@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)建默認(rèn)訂單
        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)計(jì)
        userService.updateOrderStatistics(user.getId());
        return order;
    }
}
@Service
public class NotificationService {
    @Autowired
    private UserService userService; // 另一個(gè)循環(huán)依賴
    public void sendWelcomeNotification(User user) {
        // 獲取用戶偏好設(shè)置
        UserPreference preference = userService.getUserPreference(user.getId());
        if (preference.isEmailEnabled()) {
            emailService.sendWelcomeEmail(user);
        }
        if (preference.isSmsEnabled()) {
            smsService.sendWelcomeSms(user);
        }
    }
}

解決方案:

/**
 * 重構(gòu)后的解決方案:使用事件驅(qū)動(dòng)架構(gòu)
 */
@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)用其他服務(wù)
        eventPublisher.publishEvent(new UserCreatedEvent(user));
        return user;
    }
    public void updateOrderStatistics(Long userId) {
        // 更新用戶訂單統(tǒng)計(jì)
        User user = userRepository.findById(userId);
        user.incrementOrderCount();
        userRepository.save(user);
    }
    public UserPreference getUserPreference(Long userId) {
        return userPreferenceRepository.findByUserId(userId);
    }
}
@Service
public class OrderService {
    // 移除對(duì)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 {
    // 移除對(duì)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:復(fù)雜的業(yè)務(wù)場(chǎng)景循環(huán)依賴

/**
 * 電商系統(tǒng)中的復(fù)雜循環(huán)依賴場(chǎng)景
 */
@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());
        // 獲取庫(kù)存信息
        Inventory inventory = inventoryService.getInventoryWithProductInfo(productId);
        // 獲取價(jià)格信息
        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)品基本信息用于庫(kù)存展示
        ProductDTO productInfo = productService.getBasicProductInfo(productId);
        inventory.setProductInfo(productInfo);
        return inventory;
    }
}

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

/**
 * 重構(gòu)后的解決方案:分離數(shù)據(jù)訪問和業(yè)務(wù)邏輯
 */
@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. 獲取基礎(chǔ)數(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();
    }
}
// 專門的查詢服務(wù),避免循環(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)建耗時(shí)過長(zhǎ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 {} 的依賴鏈較長(zhǎng): {}", beanName, chain);
            // 檢測(cè)是否存在循環(huán)
            if (detectCircularInChain(chain)) {
                logger.error("檢測(cè)到循環(huán)依賴: {}", chain);
            }
        }
    }
    private boolean detectCircularInChain(Set<String> chain) {
        // 簡(jiǎn)化的循環(huán)檢測(cè)邏輯
        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的依賴關(guān)系
        Map<String, Set<String>> dependencyGraph = buildDependencyGraph();
        // 檢測(cè)循環(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) {
        // 實(shí)現(xiàn)依賴提取邏輯
        Set<String> dependencies = new HashSet<>();
        // 提取構(gòu)造器依賴
        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));
        // 分析啟動(dòng)過程中的循環(huán)依賴處理
        analyzeStartupPerformance();
    }
    private void analyzeStartupPerformance() {
        ApplicationContext context = applicationContext;
        // 統(tǒng)計(jì)Bean創(chuàng)建耗時(shí)
        Map<String, Long> beanCreationTimes = getBeanCreationTimes();
        // 識(shí)別耗時(shí)最長(zhǎng)的Bean
        String slowestBean = beanCreationTimes.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse("unknown");
        Long slowestTime = beanCreationTimes.get(slowestBean);
        // 記錄指標(biāo)
        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() {
        // 實(shí)現(xiàn)Bean創(chuàng)建時(shí)間統(tǒng)計(jì)
        return new HashMap<>();
    }
    private int countResolvedCircularDependencies() {
        // 統(tǒng)計(jì)解決的循環(huán)依賴數(shù)量
        return 0;
    }
}

最佳實(shí)踐總結(jié)

1. 設(shè)計(jì)原則

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

2. 代碼檢查清單

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

結(jié)論

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

關(guān)鍵要點(diǎn)回顧

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

實(shí)際應(yīng)用建議

在實(shí)際開發(fā)中,我們應(yīng)該:

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

    Mybatis中typeAliases的使用

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

    Java中泛型學(xué)習(xí)之細(xì)節(jié)篇

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

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

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

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

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

    關(guān)于SpringBoot配置文件加載位置的優(yōu)先級(jí)

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

    SpringBoot版本沖突導(dǎo)致NoSuchFieldError的解決方案

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

    關(guān)于后綴表達(dá)式的java實(shí)現(xiàn)過程

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

最新評(píng)論

禹城市| 通城县| 盐城市| 莎车县| 青海省| 青冈县| 碌曲县| 蓝山县| 志丹县| 金湖县| 简阳市| 临颍县| 土默特右旗| 阿城市| 蒙阴县| 峨眉山市| 乐昌市| 锦州市| 巫山县| 大兴区| 兴国县| 夏邑县| 梁河县| 泰和县| 绥宁县| 丽水市| 永寿县| 乐陵市| 承德县| 铁力市| 隆尧县| 桐城市| 沾化县| 通化市| 樟树市| 六安市| 奉化市| 荔波县| 武威市| 成安县| 洛川县|