From d02a3d34c3a599f61e9a20bc937b7edf24c6db6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E5=BF=97?= Date: Tue, 12 Nov 2024 19:30:38 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=E6=A8=A1=E5=9D=97=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E5=9F=BA=E5=BA=A7=E5=8D=95=E4=BE=8Bbean=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=9C=A8=E6=A8=A1=E5=9D=97=E9=94=80=E6=AF=81=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E9=94=80=E6=AF=81=E5=9F=BA=E5=BA=A7bean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- koupleless-base-plugin/pom.xml | 5 + .../ApplicationReactiveWebEnvironment.java | 50 ++++++ .../ApplicationServletEnvironment.java | 50 ++++++ ...igReactiveWebServerApplicationContext.java | 86 +++++++++ ...figServletWebServerApplicationContext.java | 97 +++++++++++ .../BizDefaultListableBeanFactory.java | 164 ++++++++++++++++++ .../DefaultApplicationContextFactory.java | 42 +++++ .../main/resources/META-INF/spring.factories | 8 +- 8 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java create mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java diff --git a/koupleless-base-plugin/pom.xml b/koupleless-base-plugin/pom.xml index eaace79f4..bc2768a75 100644 --- a/koupleless-base-plugin/pom.xml +++ b/koupleless-base-plugin/pom.xml @@ -63,6 +63,11 @@ ${sofa.ark.version} test + + org.springframework + spring-web + provided + diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java new file mode 100644 index 000000000..ac7d0f5e4 --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.context.properties.source.ConfigurationPropertySources; +import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment; +import org.springframework.core.env.ConfigurablePropertyResolver; +import org.springframework.core.env.MutablePropertySources; + +/** + * copy from {@link org.springframework.boot.web.reactive.context.ApplicationReactiveWebEnvironment} + * due to not public class + * {@link StandardReactiveWebEnvironment} for typical use in a typical + * {@link SpringApplication}. + * + * @author Phillip Webb + */ +class ApplicationReactiveWebEnvironment extends StandardReactiveWebEnvironment { + + @Override + protected String doGetActiveProfilesProperty() { + return null; + } + + @Override + protected String doGetDefaultProfilesProperty() { + return null; + } + + @Override + protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { + return ConfigurationPropertySources.createPropertyResolver(propertySources); + } + +} diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java new file mode 100644 index 000000000..bc9b0c1fe --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.context.properties.source.ConfigurationPropertySources; +import org.springframework.core.env.ConfigurablePropertyResolver; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.web.context.support.StandardServletEnvironment; + +/** + * copy from {@link org.springframework.boot.web.reactive.context.ApplicationServletEnvironment} + * due to not public class + * {@link StandardServletEnvironment} for typical use in a typical + * {@link SpringApplication}. + * + * @author Phillip Webb + */ +class ApplicationServletEnvironment extends StandardServletEnvironment { + + @Override + protected String doGetActiveProfilesProperty() { + return null; + } + + @Override + protected String doGetDefaultProfilesProperty() { + return null; + } + + @Override + protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { + return ConfigurationPropertySources.createPropertyResolver(propertySources); + } + +} diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java new file mode 100644 index 000000000..2b892af59 --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.ApplicationContextFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; + +/** + * 目的是自定义 beanFactory 的销毁行为 + * + * @author duanzhiqiang + * @version BizAnnotationConfigReactiveWebServerApplicationContext.java, v 0.1 2024年11月08日 16:23 duanzhiqiang + */ +public class BizAnnotationConfigReactiveWebServerApplicationContext extends + AnnotationConfigReactiveWebServerApplicationContext { + /** + * 构造器 + * + * @param beanFactory 指定的beanFactory + */ + public BizAnnotationConfigReactiveWebServerApplicationContext(DefaultListableBeanFactory beanFactory) { + super(beanFactory); + } + + /** + * 替换上下文创建行为利用 spring boot factories 扩展 并在默认的优先级前 + * {@link ApplicationContextFactory} registered in {@code spring.factories} to support + * {@link AnnotationConfigServletWebServerApplicationContext}. + */ + static class Factory implements ApplicationContextFactory, Ordered { + + @Override + public Class getEnvironmentType(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.REACTIVE) ? null + : ApplicationReactiveWebEnvironment.class; + } + + @Override + public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.REACTIVE) ? null + : new ApplicationReactiveWebEnvironment(); + } + + @Override + public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.REACTIVE) ? null : createContext(); + } + + /** + * 创建上下文 + * + * @return 上下文 + */ + private ConfigurableApplicationContext createContext() { + //自定义BeanFactory的销毁 + DefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); + return new BizAnnotationConfigReactiveWebServerApplicationContext(beanFactory); + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + } + +} \ No newline at end of file diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java new file mode 100644 index 000000000..6fa1d1ba9 --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.ApplicationContextFactory; +import org.springframework.boot.WebApplicationType; + +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; + +/** + * 目的是自定义 beanFactory 的销毁行为 + * + * @author duanzhiqiang + * @version BizAnnotationConfigServletWebServerApplicationContext.java, v 0.1 2024年11月08日 16:23 duanzhiqiang + */ +public class BizAnnotationConfigServletWebServerApplicationContext extends + AnnotationConfigServletWebServerApplicationContext { + /** + * 构造器 + * + * @param beanFactory 指定的beanFactory + */ + public BizAnnotationConfigServletWebServerApplicationContext(DefaultListableBeanFactory beanFactory) { + super(beanFactory); + } + + @Override + public Object getBean(String name) throws BeansException { + return super.getBean(name); + } + + @Override + public T getBean(Class requiredType, Object... args) throws BeansException { + return super.getBean(requiredType, args); + } + + /** + * 替换上下文创建行为利用 spring boot factories 扩展 并在默认的优先级前 + * {@link ApplicationContextFactory} registered in {@code spring.factories} to support + * {@link AnnotationConfigServletWebServerApplicationContext}. + */ + static class Factory implements ApplicationContextFactory, Ordered { + + @Override + public Class getEnvironmentType(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.SERVLET) ? null + : ApplicationServletEnvironment.class; + } + + @Override + public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.SERVLET) ? null + : new ApplicationServletEnvironment(); + } + + @Override + public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext(); + } + + /** + * 创建上下文 + * + * @return 上下文 + */ + private ConfigurableApplicationContext createContext() { + //自定义BeanFactory的销毁 + DefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); + return new BizAnnotationConfigServletWebServerApplicationContext(beanFactory); + } + + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } + } + +} \ No newline at end of file diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java new file mode 100644 index 000000000..944227847 --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.lang.Nullable; + +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 重写销毁方法 当bean是 来着基座的bean 注册到biz时 不进行销毁 + * + * @author duanzhiqiang + * @version BizDefaultListableBeanFactory.java, v 0.1 2024年11月08日 16:45 duanzhiqiang + */ +public class BizDefaultListableBeanFactory extends DefaultListableBeanFactory { + + /** + * 是否是基座beanFactory + */ + private final boolean isBaseBeanFactory; + + /** + * 在创建时 额外判断是否是基座bean + */ + public BizDefaultListableBeanFactory() { + super(); + this.isBaseBeanFactory = !isOnBiz(); + } + + /** + * 当前正在销毁的单例bean + */ + private static final ThreadLocal CUR_DESTROY_SINGLE_BEAN_HOLDER = new ThreadLocal<>(); + + /** + * 基座bean复用bean集合 + */ + private static final Set BASE_RESUE_BEAN_SET = Collections + .newSetFromMap(new ConcurrentHashMap<>()); + + private static final String BIZ_CLASSLOADER = "com.alipay.sofa.ark.container.service.classloader.BizClassLoader"; + + /** + * 在子模块获取 base 的bean 记录这个bean 引用 + * + * @param name the name of the bean to retrieve + * @param requiredType the required type of the bean to retrieve + * @param args arguments to use when creating a bean instance using explicit arguments + * (only applied when creating a new instance as opposed to retrieving an existing one) + * @param typeCheckOnly whether the instance is obtained for a type check, + * not for actual use + * @param the required type of the bean to retrieve + * @return bean + * @throws BeansException 异常 + */ + @Override + protected T doGetBean(String name, Class requiredType, Object[] args, + boolean typeCheckOnly) throws BeansException { + + T bean = super.doGetBean(name, requiredType, args, typeCheckOnly); + try { + //复用基座的bean时 记录下复用的基座bean + if (isSingleton(name) && isOnBiz() && isBaseBeanFactory) { + BASE_RESUE_BEAN_SET.add(bean); + } + } catch (Exception e) { + logger.error("记录复用基座bean异常", e); + } + return bean; + } + + /** + * 在模块卸载时 getBeanFactory().destroySingletons(); + * 最终会调用 下面的方法 + * Destroy the given bean. Must destroy beans that depend on the given + * bean before the bean itself. Should not throw any exceptions. + * + * @param beanName the name of the bean + * @param bean the bean instance to destroy + */ + protected void destroyBean(String beanName, @Nullable DisposableBean bean) { + if (!isBaseBeanFactory && isBaseBean()) { + //传为null时不进行销毁 + super.destroyBean(beanName, null); + return; + } + super.destroyBean(beanName, bean); + + } + + /** + * 单例bean销毁是 在线程上下文记录下当前销毁的bean 只在子模块中生效 + * + * @param beanName the name of the bean + */ + @Override + public void destroySingleton(String beanName) { + if (!isBaseBeanFactory) { + try { + Object bean = getBean(beanName); + CUR_DESTROY_SINGLE_BEAN_HOLDER.set(bean); + super.destroySingleton(beanName); + } finally { + CUR_DESTROY_SINGLE_BEAN_HOLDER.remove(); + } + } else { + super.destroySingleton(beanName); + } + } + + /** + * 判断是否是基座的bean + * 基于记录了那些跨模块的bean + * + * @return true 是基座的bean + */ + private boolean isBaseBean() { + Object curDestroySingleBean = CUR_DESTROY_SINGLE_BEAN_HOLDER.get(); + if (curDestroySingleBean != null) { + return BASE_RESUE_BEAN_SET.contains(curDestroySingleBean); + } + return false; + } + + /** + * 判断是否在biz中 而不是基座中 + * + * @return true 在biz中 + */ + private boolean isOnBiz() { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + return contextClassLoader == null + || BIZ_CLASSLOADER.equals(contextClassLoader.getClass().getName()); + } + + /** + * Getter method for property isBase. + * + * @return property value of isBase + */ + public boolean isBaseBeanFactory() { + return isBaseBeanFactory; + } + +} \ No newline at end of file diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java new file mode 100644 index 000000000..9955a7695 --- /dev/null +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.plugin.context; + +import org.springframework.boot.ApplicationContextFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.Ordered; + +/** + * WebApplicationType.NONE 自定义上下文 + * + * @author duanzhiqiang + * @version DefaultApplicationContextFactory.java, v 0.1 2024年11月12日 17:55 duanzhiqiang + */ +public class DefaultApplicationContextFactory implements ApplicationContextFactory, Ordered { + @Override + public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.NONE) ? null + : new AnnotationConfigApplicationContext(new BizDefaultListableBeanFactory()); + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } +} \ No newline at end of file diff --git a/koupleless-base-plugin/src/main/resources/META-INF/spring.factories b/koupleless-base-plugin/src/main/resources/META-INF/spring.factories index 1cda1a4c4..11a982c2b 100644 --- a/koupleless-base-plugin/src/main/resources/META-INF/spring.factories +++ b/koupleless-base-plugin/src/main/resources/META-INF/spring.factories @@ -12,4 +12,10 @@ org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ com.alipay.sofa.koupleless.plugin.spring.SkipAutoConfigurationImportFilter org.springframework.context.ApplicationContextInitializer=\ - com.alipay.sofa.koupleless.plugin.spring.BizApplicationContextInitializer \ No newline at end of file + com.alipay.sofa.koupleless.plugin.spring.BizApplicationContextInitializer + + +org.springframework.boot.ApplicationContextFactory=\ +com.alipay.sofa.koupleless.plugin.context.BizAnnotationConfigReactiveWebServerApplicationContext.Factory,\ +com.alipay.sofa.koupleless.plugin.context.BizAnnotationConfigServletWebServerApplicationContext.Factory, \ +com.alipay.sofa.koupleless.plugin.context.DefaultApplicationContextFactory \ No newline at end of file From bdf5a04cfd73037aed84da53d4fdcda6d2343d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E5=BF=97?= Date: Wed, 13 Nov 2024 15:11:04 +0800 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=E5=8E=BB=E6=8E=89=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E7=9A=84ApplicationEnvironment=E7=9A=84=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApplicationReactiveWebEnvironment.java | 50 ------------------- .../ApplicationServletEnvironment.java | 50 ------------------- ...igReactiveWebServerApplicationContext.java | 20 ++------ ...figServletWebServerApplicationContext.java | 32 ++---------- .../BizDefaultListableBeanFactory.java | 43 ++++++++++------ .../DefaultApplicationContextFactory.java | 9 +++- 6 files changed, 45 insertions(+), 159 deletions(-) delete mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java delete mode 100644 koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java deleted file mode 100644 index ac7d0f5e4..000000000 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationReactiveWebEnvironment.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alipay.sofa.koupleless.plugin.context; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment; -import org.springframework.core.env.ConfigurablePropertyResolver; -import org.springframework.core.env.MutablePropertySources; - -/** - * copy from {@link org.springframework.boot.web.reactive.context.ApplicationReactiveWebEnvironment} - * due to not public class - * {@link StandardReactiveWebEnvironment} for typical use in a typical - * {@link SpringApplication}. - * - * @author Phillip Webb - */ -class ApplicationReactiveWebEnvironment extends StandardReactiveWebEnvironment { - - @Override - protected String doGetActiveProfilesProperty() { - return null; - } - - @Override - protected String doGetDefaultProfilesProperty() { - return null; - } - - @Override - protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { - return ConfigurationPropertySources.createPropertyResolver(propertySources); - } - -} diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java deleted file mode 100644 index bc9b0c1fe..000000000 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/ApplicationServletEnvironment.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alipay.sofa.koupleless.plugin.context; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.core.env.ConfigurablePropertyResolver; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.web.context.support.StandardServletEnvironment; - -/** - * copy from {@link org.springframework.boot.web.reactive.context.ApplicationServletEnvironment} - * due to not public class - * {@link StandardServletEnvironment} for typical use in a typical - * {@link SpringApplication}. - * - * @author Phillip Webb - */ -class ApplicationServletEnvironment extends StandardServletEnvironment { - - @Override - protected String doGetActiveProfilesProperty() { - return null; - } - - @Override - protected String doGetDefaultProfilesProperty() { - return null; - } - - @Override - protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { - return ConfigurationPropertySources.createPropertyResolver(propertySources); - } - -} diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java index 2b892af59..7782f1730 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigReactiveWebServerApplicationContext.java @@ -23,16 +23,18 @@ import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; /** * 目的是自定义 beanFactory 的销毁行为 + * 1、基于Spring Boot ApplicationContextFactory SPI扩展 当WebApplicationType.REACTIVE创建一个上下文 和父类的区别是指定了自定义的BeanFactory + * 2、仅处理WebApplicationType.REACTIVE 当返回为null时 有其他SPI扩展去处理 即其他ApplicationContextFactory去处理 不同的WebApplicationType + * 3、指定 BizDefaultListableBeanFactory{@link com.alipay.sofa.koupleless.plugin.context.BizDefaultListableBeanFactory} 来自定义子模块的销毁行为 * * @author duanzhiqiang * @version BizAnnotationConfigReactiveWebServerApplicationContext.java, v 0.1 2024年11月08日 16:23 duanzhiqiang */ public class BizAnnotationConfigReactiveWebServerApplicationContext extends - AnnotationConfigReactiveWebServerApplicationContext { + AnnotationConfigReactiveWebServerApplicationContext { /** * 构造器 * @@ -49,18 +51,6 @@ public BizAnnotationConfigReactiveWebServerApplicationContext(DefaultListableBea */ static class Factory implements ApplicationContextFactory, Ordered { - @Override - public Class getEnvironmentType(WebApplicationType webApplicationType) { - return (webApplicationType != WebApplicationType.REACTIVE) ? null - : ApplicationReactiveWebEnvironment.class; - } - - @Override - public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) { - return (webApplicationType != WebApplicationType.REACTIVE) ? null - : new ApplicationReactiveWebEnvironment(); - } - @Override public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { return (webApplicationType != WebApplicationType.REACTIVE) ? null : createContext(); @@ -73,7 +63,7 @@ public ConfigurableApplicationContext create(WebApplicationType webApplicationTy */ private ConfigurableApplicationContext createContext() { //自定义BeanFactory的销毁 - DefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); + BizDefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); return new BizAnnotationConfigReactiveWebServerApplicationContext(beanFactory); } diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java index 6fa1d1ba9..8c3c20ab3 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizAnnotationConfigServletWebServerApplicationContext.java @@ -16,18 +16,18 @@ */ package com.alipay.sofa.koupleless.plugin.context; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.ApplicationContextFactory; import org.springframework.boot.WebApplicationType; - import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; /** * 目的是自定义 beanFactory 的销毁行为 + * 1、基于Spring Boot ApplicationContextFactory SPI扩展 当WebApplicationType.SERVLET创建一个上下文 和父类的区别是指定了自定义的BeanFactory + * 2、仅处理WebApplicationType.SERVLET 当返回为null时 有其他SPI扩展去处理 即其他ApplicationContextFactory去处理 不同的WebApplicationType + * 3、指定 BizDefaultListableBeanFactory{@link com.alipay.sofa.koupleless.plugin.context.BizDefaultListableBeanFactory} 来自定义子模块的销毁行为 * * @author duanzhiqiang * @version BizAnnotationConfigServletWebServerApplicationContext.java, v 0.1 2024年11月08日 16:23 duanzhiqiang @@ -35,7 +35,7 @@ public class BizAnnotationConfigServletWebServerApplicationContext extends AnnotationConfigServletWebServerApplicationContext { /** - * 构造器 + * 构造器 并使用自定义的 beanFactory * * @param beanFactory 指定的beanFactory */ @@ -43,16 +43,6 @@ public BizAnnotationConfigServletWebServerApplicationContext(DefaultListableBean super(beanFactory); } - @Override - public Object getBean(String name) throws BeansException { - return super.getBean(name); - } - - @Override - public T getBean(Class requiredType, Object... args) throws BeansException { - return super.getBean(requiredType, args); - } - /** * 替换上下文创建行为利用 spring boot factories 扩展 并在默认的优先级前 * {@link ApplicationContextFactory} registered in {@code spring.factories} to support @@ -60,18 +50,6 @@ public T getBean(Class requiredType, Object... args) throws BeansExceptio */ static class Factory implements ApplicationContextFactory, Ordered { - @Override - public Class getEnvironmentType(WebApplicationType webApplicationType) { - return (webApplicationType != WebApplicationType.SERVLET) ? null - : ApplicationServletEnvironment.class; - } - - @Override - public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) { - return (webApplicationType != WebApplicationType.SERVLET) ? null - : new ApplicationServletEnvironment(); - } - @Override public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext(); @@ -84,7 +62,7 @@ public ConfigurableApplicationContext create(WebApplicationType webApplicationTy */ private ConfigurableApplicationContext createContext() { //自定义BeanFactory的销毁 - DefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); + BizDefaultListableBeanFactory beanFactory = new BizDefaultListableBeanFactory(); return new BizAnnotationConfigServletWebServerApplicationContext(beanFactory); } diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java index 944227847..50e6dad32 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java @@ -26,7 +26,10 @@ import java.util.concurrent.ConcurrentHashMap; /** - * 重写销毁方法 当bean是 来着基座的bean 注册到biz时 不进行销毁 + * 1、重写销毁方法 当bean是 来着基座的bean 注册到biz时 不进行销毁 + * 2、当模块获取基座单例时bean 记录引用 + * 3、模块销毁单例bean 在 + * 4、当模块销毁时如果bean时复用的基座bean此时不执行DisposableBean.destroy * * @author duanzhiqiang * @version BizDefaultListableBeanFactory.java, v 0.1 2024年11月08日 16:45 duanzhiqiang @@ -38,6 +41,13 @@ public class BizDefaultListableBeanFactory extends DefaultListableBeanFactory { */ private final boolean isBaseBeanFactory; + /** + * 不做任务事情销毁 用于基座bean在子模块bean生命周期 销毁时不进行销毁 + */ + private final static DisposableBean DO_NOTHING_DISPOSABLE_BEAN = () -> { + //do nothing + }; + /** * 在创建时 额外判断是否是基座bean */ @@ -52,12 +62,14 @@ public BizDefaultListableBeanFactory() { private static final ThreadLocal CUR_DESTROY_SINGLE_BEAN_HOLDER = new ThreadLocal<>(); /** - * 基座bean复用bean集合 + * 基座bean复用bean集合引用 */ - private static final Set BASE_RESUE_BEAN_SET = Collections - .newSetFromMap(new ConcurrentHashMap<>()); + private static final Set BASE_FACTORTY_REUSE_BEAN_SET = Collections.newSetFromMap(new ConcurrentHashMap<>()); - private static final String BIZ_CLASSLOADER = "com.alipay.sofa.ark.container.service.classloader.BizClassLoader"; + /** + * 模块的类加载器名 + */ + private static final String BIZ_CLASSLOADER = "com.alipay.sofa.ark.container.service.classloader.BizClassLoader"; /** * 在子模块获取 base 的bean 记录这个bean 引用 @@ -77,14 +89,12 @@ protected T doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly) throws BeansException { T bean = super.doGetBean(name, requiredType, args, typeCheckOnly); - try { - //复用基座的bean时 记录下复用的基座bean - if (isSingleton(name) && isOnBiz() && isBaseBeanFactory) { - BASE_RESUE_BEAN_SET.add(bean); - } - } catch (Exception e) { - logger.error("记录复用基座bean异常", e); + + // 只有是基座isBaseBeanFactory 但获取bean时是模块发起调用(即复用基座的bean时) 记录下复用的基座bean + if (isBaseBeanFactory && isOnBiz() && isSingleton(name)) { + BASE_FACTORTY_REUSE_BEAN_SET.add(bean); } + return bean; } @@ -98,9 +108,10 @@ protected T doGetBean(String name, Class requiredType, Object[] args, * @param bean the bean instance to destroy */ protected void destroyBean(String beanName, @Nullable DisposableBean bean) { + //基座被复用bean在销毁这个bean时 替换销毁行为 if (!isBaseBeanFactory && isBaseBean()) { - //传为null时不进行销毁 - super.destroyBean(beanName, null); + //传为null时不进行销毁 DisposableBean + super.destroyBean(beanName, DO_NOTHING_DISPOSABLE_BEAN); return; } super.destroyBean(beanName, bean); @@ -136,7 +147,7 @@ public void destroySingleton(String beanName) { private boolean isBaseBean() { Object curDestroySingleBean = CUR_DESTROY_SINGLE_BEAN_HOLDER.get(); if (curDestroySingleBean != null) { - return BASE_RESUE_BEAN_SET.contains(curDestroySingleBean); + return BASE_FACTORTY_REUSE_BEAN_SET.contains(curDestroySingleBean); } return false; } @@ -149,7 +160,7 @@ private boolean isBaseBean() { private boolean isOnBiz() { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); return contextClassLoader == null - || BIZ_CLASSLOADER.equals(contextClassLoader.getClass().getName()); + || BIZ_CLASSLOADER.equals(contextClassLoader.getClass().getName()); } /** diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java index 9955a7695..aeac4f68a 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/DefaultApplicationContextFactory.java @@ -24,6 +24,13 @@ /** * WebApplicationType.NONE 自定义上下文 + * 1、基于Spring Boot ApplicationContextFactory SPI扩展 当WebApplicationType.NONE创建一个上下文 + * 2、仅处理WebApplicationType.NONE 当返回为null时 有其他SPI扩展去处理 即其他ApplicationContextFactory去处理 不同的WebApplicationType + * 3、指定 BizDefaultListableBeanFactory{@link com.alipay.sofa.koupleless.plugin.context.BizDefaultListableBeanFactory} 来自定义子模块的销毁行为 + *

+ * Custom ApplicationContextFactory for WebApplicationType.NONE that uses BizDefaultListableBeanFactory + * to prevent destruction of base singleton beans when a module is destroyed. + * This factory has the highest precedence and only handles non-web application contexts. * * @author duanzhiqiang * @version DefaultApplicationContextFactory.java, v 0.1 2024年11月12日 17:55 duanzhiqiang @@ -32,7 +39,7 @@ public class DefaultApplicationContextFactory implements ApplicationContextFacto @Override public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { return (webApplicationType != WebApplicationType.NONE) ? null - : new AnnotationConfigApplicationContext(new BizDefaultListableBeanFactory()); + : new AnnotationConfigApplicationContext(new BizDefaultListableBeanFactory()); } @Override From d81d6015505e41cdd8446c820420b8aaacf63508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E5=BF=97?= Date: Thu, 14 Nov 2024 16:08:44 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=E9=94=80=E6=AF=81=E6=97=B6=E4=B9=9F?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E5=88=9B=E5=BB=BAbean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/context/BizDefaultListableBeanFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java index 50e6dad32..06916bef4 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java @@ -127,7 +127,8 @@ protected void destroyBean(String beanName, @Nullable DisposableBean bean) { public void destroySingleton(String beanName) { if (!isBaseBeanFactory) { try { - Object bean = getBean(beanName); + //获取给定名称下注册的 (原始) singleton 对象。即需要销毁原始对象 + Object bean = this.getSingleton(beanName); CUR_DESTROY_SINGLE_BEAN_HOLDER.set(bean); super.destroySingleton(beanName); } finally { From ac919813cb50b5b478b9fb89738f41d0b5928509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E5=BF=97?= Date: Fri, 15 Nov 2024 10:53:09 +0800 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=E5=9C=A8=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E8=BF=99=E4=B8=AA=E5=A4=8D=E7=94=A8=E7=9A=84?= =?UTF-8?q?bean=E6=97=B6=20=E4=B8=8D=E6=B3=A8=E5=86=8C=E9=94=80=E6=AF=81?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=20=20=E6=94=AF=E6=8C=81=E5=A4=8D=E7=94=A8bea?= =?UTF-8?q?n=E4=B8=BA=E6=B3=A8=E5=86=8C=E5=8D=95=E4=BE=8B=E6=88=96?= =?UTF-8?q?=E8=80=85=E6=98=AF=E5=85=B6=E4=BB=96scope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BizDefaultListableBeanFactory.java | 81 +++++-------------- 1 file changed, 20 insertions(+), 61 deletions(-) diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java index 06916bef4..8180a8e1d 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java @@ -17,19 +17,17 @@ package com.alipay.sofa.koupleless.plugin.context; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.lang.Nullable; +import org.springframework.beans.factory.support.RootBeanDefinition; import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** - * 1、重写销毁方法 当bean是 来着基座的bean 注册到biz时 不进行销毁 - * 2、当模块获取基座单例时bean 记录引用 - * 3、模块销毁单例bean 在 - * 4、当模块销毁时如果bean时复用的基座bean此时不执行DisposableBean.destroy + * 1、当模块获取基座单例时bean 记录引用(由于无法通过名称获取bean 因为在子模块中 beanName是可以重新定义的) + * 2、在模块创建这个复用的bean时 不注册销毁行为 支持复用bean 注册单例或者是其他scope + * 3、通过记录的复用的bean 引用来判断是基座复用bean * * @author duanzhiqiang * @version BizDefaultListableBeanFactory.java, v 0.1 2024年11月08日 16:45 duanzhiqiang @@ -41,13 +39,6 @@ public class BizDefaultListableBeanFactory extends DefaultListableBeanFactory { */ private final boolean isBaseBeanFactory; - /** - * 不做任务事情销毁 用于基座bean在子模块bean生命周期 销毁时不进行销毁 - */ - private final static DisposableBean DO_NOTHING_DISPOSABLE_BEAN = () -> { - //do nothing - }; - /** * 在创建时 额外判断是否是基座bean */ @@ -56,11 +47,6 @@ public BizDefaultListableBeanFactory() { this.isBaseBeanFactory = !isOnBiz(); } - /** - * 当前正在销毁的单例bean - */ - private static final ThreadLocal CUR_DESTROY_SINGLE_BEAN_HOLDER = new ThreadLocal<>(); - /** * 基座bean复用bean集合引用 */ @@ -99,58 +85,31 @@ protected T doGetBean(String name, Class requiredType, Object[] args, } /** - * 在模块卸载时 getBeanFactory().destroySingletons(); - * 最终会调用 下面的方法 - * Destroy the given bean. Must destroy beans that depend on the given - * bean before the bean itself. Should not throw any exceptions. - * - * @param beanName the name of the bean - * @param bean the bean instance to destroy - */ - protected void destroyBean(String beanName, @Nullable DisposableBean bean) { - //基座被复用bean在销毁这个bean时 替换销毁行为 - if (!isBaseBeanFactory && isBaseBean()) { - //传为null时不进行销毁 DisposableBean - super.destroyBean(beanName, DO_NOTHING_DISPOSABLE_BEAN); - return; - } - super.destroyBean(beanName, bean); - - } - - /** - * 单例bean销毁是 在线程上下文记录下当前销毁的bean 只在子模块中生效 + * 判断是否需要销毁 + * 扩展如果是模块上下文且是基座复用的bean 则不需要进行销毁 * - * @param beanName the name of the bean + * @param bean the bean instance to check + * @param mbd the corresponding bean definition + * @return false 不需要销毁 true 需要销毁 */ @Override - public void destroySingleton(String beanName) { - if (!isBaseBeanFactory) { - try { - //获取给定名称下注册的 (原始) singleton 对象。即需要销毁原始对象 - Object bean = this.getSingleton(beanName); - CUR_DESTROY_SINGLE_BEAN_HOLDER.set(bean); - super.destroySingleton(beanName); - } finally { - CUR_DESTROY_SINGLE_BEAN_HOLDER.remove(); - } - } else { - super.destroySingleton(beanName); + protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { + //如果是模块上下文且是基座复用的bean 则不需要进行销毁 + if (!isBaseBeanFactory && isBaseReuseBean(bean)) { + //不注册DisposableBean + return false; } + return super.requiresDestruction(bean, mbd); } /** - * 判断是否是基座的bean - * 基于记录了那些跨模块的bean + * 是否是基座复用的bean * - * @return true 是基座的bean + * @param bean bean 实例 + * @return true 是 false 不是 */ - private boolean isBaseBean() { - Object curDestroySingleBean = CUR_DESTROY_SINGLE_BEAN_HOLDER.get(); - if (curDestroySingleBean != null) { - return BASE_FACTORTY_REUSE_BEAN_SET.contains(curDestroySingleBean); - } - return false; + private boolean isBaseReuseBean(Object bean) { + return BASE_FACTORTY_REUSE_BEAN_SET.contains(bean); } /** From 195c6f08249ede00eedb557485331bc1b939e11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E5=BF=97?= Date: Fri, 15 Nov 2024 16:57:35 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix:=E6=9C=AA=E6=B8=85=E9=99=A4bean?= =?UTF-8?q?=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../context/BizDefaultListableBeanFactory.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java index 8180a8e1d..04c652aab 100644 --- a/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java +++ b/koupleless-base-plugin/src/main/java/com/alipay/sofa/koupleless/plugin/context/BizDefaultListableBeanFactory.java @@ -50,7 +50,7 @@ public BizDefaultListableBeanFactory() { /** * 基座bean复用bean集合引用 */ - private static final Set BASE_FACTORTY_REUSE_BEAN_SET = Collections.newSetFromMap(new ConcurrentHashMap<>()); + private static final Set BASE_FACTORY_REUSE_BEAN_SET = Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * 模块的类加载器名 @@ -78,12 +78,21 @@ protected T doGetBean(String name, Class requiredType, Object[] args, // 只有是基座isBaseBeanFactory 但获取bean时是模块发起调用(即复用基座的bean时) 记录下复用的基座bean if (isBaseBeanFactory && isOnBiz() && isSingleton(name)) { - BASE_FACTORTY_REUSE_BEAN_SET.add(bean); + BASE_FACTORY_REUSE_BEAN_SET.add(bean); } return bean; } + @Override + public void destroySingletons() { + super.destroySingletons(); + //复用bean在 基座销毁时清空 + if (isBaseBeanFactory) { + BASE_FACTORY_REUSE_BEAN_SET.clear(); + } + } + /** * 判断是否需要销毁 * 扩展如果是模块上下文且是基座复用的bean 则不需要进行销毁 @@ -109,7 +118,7 @@ protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { * @return true 是 false 不是 */ private boolean isBaseReuseBean(Object bean) { - return BASE_FACTORTY_REUSE_BEAN_SET.contains(bean); + return BASE_FACTORY_REUSE_BEAN_SET.contains(bean); } /**