enable spring context holder

pull/836/head
leojames 2023-12-27 17:29:23 +08:00
parent 4792b06312
commit fcae3766d3
4 changed files with 41 additions and 24 deletions

View File

@ -16,6 +16,7 @@
package me.zhengjie.utils; package me.zhengjie.utils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -24,7 +25,10 @@ import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author Jie * @author Jie
@ -33,9 +37,9 @@ import java.util.List;
@Slf4j @Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean { public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null; private static Map<ClassLoader, ApplicationContext> applicationContextMap = new ConcurrentHashMap<>();
private static final List<CallBack> CALL_BACKS = new ArrayList<>(); private static final Map<ClassLoader, List<CallBack>> CALL_BACKS_MAP = new HashMap<>();
private static boolean addCallback = true; private static Map<ClassLoader, Boolean> addCallbackMap = new HashMap<>();
/** /**
* SpringContextHolder * SpringContextHolder
@ -44,8 +48,12 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* @param callBack * @param callBack
*/ */
public synchronized static void addCallBacks(CallBack callBack) { public synchronized static void addCallBacks(CallBack callBack) {
if (addCallback) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
SpringContextHolder.CALL_BACKS.add(callBack);
Boolean addCallback = addCallbackMap.get(classLoader);
if (addCallback == null || BooleanUtils.isNotTrue(addCallback)) {
CALL_BACKS_MAP.putIfAbsent(classLoader, new ArrayList<>());
CALL_BACKS_MAP.get(classLoader).add(callBack);
} else { } else {
log.warn("CallBack{} 已无法添加!立即执行", callBack.getCallBackName()); log.warn("CallBack{} 已无法添加!立即执行", callBack.getCallBackName());
callBack.executor(); callBack.executor();
@ -58,7 +66,8 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T getBean(String name) { public static <T> T getBean(String name) {
assertContextInjected(); assertContextInjected();
return (T) applicationContext.getBean(name); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return (T) applicationContextMap.get(classLoader).getBean(name);
} }
/** /**
@ -66,7 +75,8 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
*/ */
public static <T> T getBean(Class<T> requiredType) { public static <T> T getBean(Class<T> requiredType) {
assertContextInjected(); assertContextInjected();
return applicationContext.getBean(requiredType); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return (T) applicationContextMap.get(classLoader).getBean(requiredType);
} }
/** /**
@ -110,6 +120,8 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* ApplicationContext. * ApplicationContext.
*/ */
private static void assertContextInjected() { private static void assertContextInjected() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
ApplicationContext applicationContext = applicationContextMap.get(classLoader);
if (applicationContext == null) { if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
@ -120,9 +132,10 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* SpringContextHolderApplicationContextNull. * SpringContextHolderApplicationContextNull.
*/ */
private static void clearHolder() { private static void clearHolder() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
log.debug("清除SpringContextHolder中的ApplicationContext:" log.debug("清除SpringContextHolder中的ApplicationContext:"
+ applicationContext); + applicationContextMap.get(classLoader));
applicationContext = null; applicationContextMap.remove(classLoader);
} }
@Override @Override
@ -132,17 +145,23 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
@Override @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextHolder.applicationContext != null) { // if (SpringContextHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); // log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
} // }
SpringContextHolder.applicationContext = applicationContext; ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (addCallback) { applicationContextMap.putIfAbsent(classLoader, applicationContext);
for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
callBack.executor(); Boolean addCallback = addCallbackMap.get(classLoader);
if (BooleanUtils.isNotTrue(addCallback)) {
List<CallBack> callBacks = CALL_BACKS_MAP.get(classLoader);
if (callBacks != null) {
for (CallBack callBack : callBacks) {
callBack.executor();
}
callBacks.clear();
} }
CALL_BACKS.clear();
} }
SpringContextHolder.addCallback = false; addCallbackMap.put(classLoader, true);
} }
/** /**
@ -150,6 +169,7 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* @return / * @return /
*/ */
public static List<String> getAllServiceBeanName() { public static List<String> getAllServiceBeanName() {
ApplicationContext applicationContext = applicationContextMap.get(Thread.currentThread().getContextClassLoader());
return new ArrayList<>(Arrays.asList(applicationContext return new ArrayList<>(Arrays.asList(applicationContext
.getBeanNamesForAnnotation(Service.class))); .getBeanNamesForAnnotation(Service.class)));
} }

View File

@ -15,7 +15,6 @@
*/ */
package me.zhengjie; package me.zhengjie;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import me.zhengjie.annotation.rest.AnonymousGetMapping; import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.utils.SpringContextHolder; import me.zhengjie.utils.SpringContextHolder;
@ -55,7 +54,7 @@ import java.util.List;
@EnableAsync @EnableAsync
@RestController @RestController
@Api(hidden = true) @Api(hidden = true)
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class) @SpringBootApplication
@EnableTransactionManagement @EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "auditorAware") @EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class AppRun { public class AppRun {

View File

@ -32,7 +32,6 @@ import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoi
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier; import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.ApplicationPidFileWriter; import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -55,7 +54,7 @@ import java.util.List;
@EnableAsync @EnableAsync
@RestController @RestController
@Api(hidden = true) @Api(hidden = true)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @SpringBootApplication
@EnableTransactionManagement @EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "auditorAware") @EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class AppRun { public class AppRun {

View File

@ -32,7 +32,6 @@ import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoi
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier; import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.ApplicationPidFileWriter; import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -55,7 +54,7 @@ import java.util.List;
@EnableAsync @EnableAsync
@RestController @RestController
@Api(hidden = true) @Api(hidden = true)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @SpringBootApplication
@EnableTransactionManagement @EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "auditorAware") @EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class AppRun { public class AppRun {