From d80598c29b20717f28f3bfb2c65bb0e310719b76 Mon Sep 17 00:00:00 2001 From: Ticsmyc Date: Tue, 25 May 2021 17:53:31 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=8D=95=E4=BE=8BBean=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E4=B8=80=E4=B8=AA=E7=BA=BF=E7=A8=8B=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../factory/AbstractBeanFactory.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java b/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java index aa54786..72643c0 100644 --- a/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java +++ b/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java @@ -15,13 +15,10 @@ public Object getBean(String name) throws Exception { if(beanDefinition == null) { throw new RuntimeException("Unable to find the bean of this name, please check!"); } - if(!beanDefinition.isSingleton() || beanDefinition.getBean() == null) { - return doCreateBean(beanDefinition); - } else { - return doCreateBean(beanDefinition); - } + return getBeanFromBeanDefinition(beanDefinition); } + @Override public Object getBean(Class clazz) throws Exception { BeanDefinition beanDefinition = null; @@ -34,11 +31,30 @@ public Object getBean(Class clazz) throws Exception { if(beanDefinition == null) { throw new RuntimeException("Unable to find the bean of this class, please check!"); } - if(!beanDefinition.isSingleton() || beanDefinition.getBean() == null) { + return getBeanFromBeanDefinition(beanDefinition); + } + + private Object getBeanFromBeanDefinition(BeanDefinition beanDefinition) throws Exception { + if(beanDefinition.isSingleton()){ + if(beanDefinition.getBean()!=null){ + return beanDefinition.getBean(); + }else{ + /** + * bug场景 :当多个线程使用同一个BeanFactory,针对同一个单例的beanDefinition 调用getBean + * 如果没有锁,会创建多个对象 + */ + synchronized (this){ + if(beanDefinition.getBean()==null){ + return doCreateBean(beanDefinition); + }else{ + return beanDefinition.getBean(); + } + } + } + }else{ return doCreateBean(beanDefinition); - } else { - return beanDefinition.getBean(); } + } @Override From 5bce6996340b80e1ea0b89d1c046725c7babe439 Mon Sep 17 00:00:00 2001 From: Ticsmyc Date: Tue, 25 May 2021 18:09:05 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../factory/AbstractBeanFactory.java | 11 ++++- .../factory/AutowiredCapableBeanFactory.java | 41 ++++++++++++++----- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java b/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java index 72643c0..4989b49 100644 --- a/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java +++ b/src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java @@ -2,6 +2,7 @@ import top.guoziyang.springframework.entity.BeanDefinition; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -9,6 +10,8 @@ public abstract class AbstractBeanFactory implements BeanFactory { ConcurrentHashMap beanDefinitionMap = new ConcurrentHashMap<>(); + ThreadLocal> earylyBean = new ThreadLocal>(); + @Override public Object getBean(String name) throws Exception { BeanDefinition beanDefinition = beanDefinitionMap.get(name); @@ -52,7 +55,13 @@ private Object getBeanFromBeanDefinition(BeanDefinition beanDefinition) throws E } } }else{ - return doCreateBean(beanDefinition); + //不是单例 先从earlyBean中找,如果没有就新创建 + HashMap earlyBeanMap = earylyBean.get(); + if(earlyBeanMap!=null && earlyBeanMap.containsKey(beanDefinition.getBeanClassName())){ + return earlyBeanMap.get(beanDefinition.getBeanClassName()); + }else{ + return doCreateBean(beanDefinition); + } } } diff --git a/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java b/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java index 056ed10..02aac45 100644 --- a/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java +++ b/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java @@ -5,6 +5,7 @@ import top.guoziyang.springframework.entity.PropertyValue; import java.lang.reflect.Field; +import java.util.HashMap; public class AutowiredCapableBeanFactory extends AbstractBeanFactory { @@ -15,6 +16,8 @@ Object doCreateBean(BeanDefinition beanDefinition) throws Exception { } Object bean = beanDefinition.getBeanClass().newInstance(); if(beanDefinition.isSingleton()) { + //如果是单例,就算没有完成属性赋值,也可以存起来 + //这样可以直接避免出现循环依赖导致的死循环问题 beanDefinition.setBean(bean); } applyPropertyValues(bean, beanDefinition); @@ -36,25 +39,16 @@ void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exce // 优先按照自定义名称匹配 BeanDefinition refDefinition = beanDefinitionMap.get(beanReference.getName()); if(refDefinition != null) { - if(!refDefinition.isSingleton() || refDefinition.getBean() == null) { - value = doCreateBean(refDefinition); - } else { - value = refDefinition.getBean(); - } + value = createBeanFromBeanDefinition(bean, beanDefinition, beanReference, refDefinition); } else { // 按照类型匹配,返回第一个匹配的 Class clazz = Class.forName(beanReference.getName()); for(BeanDefinition definition : beanDefinitionMap.values()) { if(clazz.isAssignableFrom(definition.getBeanClass())) { - if(!definition.isSingleton() || definition.getBean() == null) { - value = doCreateBean(definition); - } else { - value = definition.getBean(); - } + value = createBeanFromBeanDefinition(bean, beanDefinition, beanReference, refDefinition); } } } - } if(value == null) { throw new RuntimeException("无法注入"); @@ -62,6 +56,31 @@ void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exce field.setAccessible(true); field.set(bean, value); } + //如果自己在earlyBean里,就删除 + if(earylyBean.get()!=null && earylyBean.get().containsKey(beanDefinition.getBeanClassName())){ + earylyBean.get().remove(beanDefinition.getBeanClassName()); + } + } + + private Object createBeanFromBeanDefinition(Object bean, BeanDefinition beanDefinition, BeanReference beanReference, BeanDefinition refDefinition) throws Exception { + if(refDefinition.isSingleton()){ + //单例就直接拿 + if(refDefinition.getBean()!=null){ + return refDefinition.getBean(); + }else{ + return doCreateBean(refDefinition); + } + }else{ + //先把自己放入earlyBean + if(earylyBean.get() == null){ + earylyBean.set(new HashMap<>()); + } + if(!earylyBean.get().containsKey(beanDefinition.getBeanClassName())){ + earylyBean.get().put(beanDefinition.getBeanClassName(), bean); + } + //再尝试获取所需的Bean + return getBean(beanReference.getName()); + } } From 32043673fefd74720501a98e5017e0f987be144f Mon Sep 17 00:00:00 2001 From: Ticsmyc Date: Thu, 14 Oct 2021 11:35:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fixbug=EF=BC=9A=E7=A9=BA=E6=8C=87=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springframework/factory/AutowiredCapableBeanFactory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java b/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java index 02aac45..e247127 100644 --- a/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java +++ b/src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java @@ -45,7 +45,7 @@ void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exce Class clazz = Class.forName(beanReference.getName()); for(BeanDefinition definition : beanDefinitionMap.values()) { if(clazz.isAssignableFrom(definition.getBeanClass())) { - value = createBeanFromBeanDefinition(bean, beanDefinition, beanReference, refDefinition); + value = createBeanFromBeanDefinition(bean, beanDefinition, beanReference, definition); } } } @@ -62,7 +62,8 @@ void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exce } } - private Object createBeanFromBeanDefinition(Object bean, BeanDefinition beanDefinition, BeanReference beanReference, BeanDefinition refDefinition) throws Exception { + private Object createBeanFromBeanDefinition(Object bean, BeanDefinition beanDefinition, BeanReference beanReference, + BeanDefinition refDefinition) throws Exception { if(refDefinition.isSingleton()){ //单例就直接拿 if(refDefinition.getBean()!=null){