Skip to content

Commit

Permalink
[Advance][Circular dependency][fix] resolve circular use second third…
Browse files Browse the repository at this point in the history
… cache
  • Loading branch information
m1a2st committed Jul 26, 2023
1 parent 822a461 commit 7ed4940
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.m1a2st.beans.factory.support.DefaultListableBeanFactory;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
* @Author m1a2st
Expand All @@ -23,6 +25,8 @@ public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPos

private DefaultListableBeanFactory beanFactory;

private final Set<Object> earlyProxyReferences = new HashSet<>();

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
Expand All @@ -38,8 +42,21 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) throw
return true;
}

@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
earlyProxyReferences.add(beanName);
return wrapIfNecessary(bean, beanName);
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!earlyProxyReferences.contains(beanName)) {
return wrapIfNecessary(bean, beanName);
}
return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName) {
// 避免死循環
if (isInfrastructureClass(bean.getClass())) {
return null;
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/m1a2st/beans/factory/ObjectFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.m1a2st.beans.factory;

import org.m1a2st.beans.BeansException;

/**
* @Author m1a2st
* @Date 2023/7/26
* @Version v1.0
*/
public interface ObjectFactory<T> {

T getObject() throws BeansException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,16 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @throws BeansException bean處理異常
*/
PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException;

/**
* 提前曝露 bean
*
* @param bean bean實例
* @param beanName bean的名稱
* @return bean實例
* @throws BeansException bean處理異常
*/
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) th
// 創造Bean 實體
bean = createBeanInstance(beanDefinition);
// 為解決循環依賴,將實例化的Bean放入緩存提前暴露
earlySingletonObjects.put(beanName, bean);
if (beanDefinition.isSingleton()) {
Object finalBean = bean;
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, beanDefinition, finalBean));
}
// bean 實例化後進行
if (!applyBeanPostProcessorsAfterInstantiation(beanName, bean)) {
return bean;
Expand All @@ -91,10 +94,27 @@ protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) th
}
// 註冊有銷毀方法的Bean
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

Object exposeObject = bean;
if (beanDefinition.isSingleton()) {
addSingleton(beanName, bean);
// 如果有代理對象,此處獲取代理對象
exposeObject = getSingleton(beanName);
addSingleton(beanName, exposeObject);
}
return bean;
return exposeObject;
}

protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object bean) {
Object exposedObject = bean;
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
exposedObject = ((InstantiationAwareBeanPostProcessor) bp).getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return null;
}
}
}
return exposedObject;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.m1a2st.beans.BeansException;
import org.m1a2st.beans.factory.DisposableBean;
import org.m1a2st.beans.factory.ObjectFactory;
import org.m1a2st.beans.factory.config.SingletonBeanRegistry;

import java.util.ArrayList;
Expand All @@ -20,22 +21,44 @@
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

// 二級緩存
protected final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
// 一級緩存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// 三級緩存
private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>();

private final Map<String, DisposableBean> disposableBeans = new ConcurrentHashMap<>();
protected final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();

@Override
public Object getSingleton(String beanName) {
Object bean = singletonObjects.get(beanName);
if (bean == null) {
bean = earlySingletonObjects.get(beanName);
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
if (singletonFactory != null) {
// 這裡的singletonObject是一個ObjectFactory,而不是bean實例
singletonObject = singletonFactory.getObject();
// 從三級緩存放進二級緩存
earlySingletonObjects.put(beanName, singletonObject);
// 從三級緩存移除
singletonFactories.remove(beanName);
}
}
}
return bean;
return singletonObject;
}

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
singletonFactories.put(beanName, singletonFactory);
}

@Override
public void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
earlySingletonObjects.remove(beanName);
singletonFactories.remove(beanName);
}

public void registerDisposableBean(String beanName, DisposableBean bean) {
Expand Down

0 comments on commit 7ed4940

Please sign in to comment.