com.paas.content.PaaSReactiveBootStrapper Maven / Gradle / Ivy
package com.paas.content;
import com.paas.aspect.RequestAspect;
import com.paas.bean.props.BootstrapProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @ClassName PaaSReactiveBootStrapper
* @Date 2020/7/23 11:06
* @Auther wangyongyong
* @Version 1.0
* @Description paas 平台容器
*/
public class PaaSReactiveBootStrapper implements SmartLifecycle
{
private static final Logger logger = LoggerFactory.getLogger(RequestAspect.class);
private static final String SPRING_STARTUP_BOOTSTRAP_ENABLE = "spring.startup.bootstrap.enable";
private static String formatMappings(Class> userType, Map methods)
{
String formattedType = Arrays.stream(ClassUtils.getPackageName(userType).split("\\."))
.map(p -> p.substring(0, 1))
.collect(Collectors.joining(".", "", "." + userType.getSimpleName()));
Function methodFormatter = method -> Arrays.stream(method.getParameterTypes())
.map(Class::getSimpleName)
.collect(Collectors.joining(",", "(", ")"));
return methods.entrySet().stream()
.map(e ->
{
Method method = e.getKey();
return e.getValue() + ": " + method.getName() + methodFormatter.apply(method);
})
.collect(Collectors.joining("\n\t", "\n\t" + formattedType + ":" + "\n\t", ""));
}
private final AtomicBoolean initialized = new AtomicBoolean(false);
@Autowired
private ConfigurableApplicationContext context;
@Override
public boolean isAutoStartup()
{
String autoStartupConfig =
context.getEnvironment().getProperty(
SPRING_STARTUP_BOOTSTRAP_ENABLE,
"false");
if (Boolean.parseBoolean(autoStartupConfig) && context.getParent() == null)
{
return true;
}
if (Boolean.parseBoolean(autoStartupConfig) && context.getParent() != null)
{
return Objects.equals(context.getParent().getId(), "bootstrap");// 是 cloud 环境,返回执行
}
return false;
}
@Override
public void stop(Runnable callback)
{
callback.run();
}
@Override
public void start()
{
if (initialized.compareAndSet(false, true))
{
logger.info("Parent Context refreshed");
ApplicationContext parentContent = context;
BootstrapProperties properties = context.getBean(BootstrapProperties.class);
ConfigurableEnvironment configurableEnvironment = context.getEnvironment();
List> mainClasses = properties.getMainClasses();
if (!CollectionUtils.isEmpty(mainClasses))
{
for (Class> mainClass : mainClasses)
{
AnnotationConfigApplicationContext serviceContent = new AnnotationConfigApplicationContext();
serviceContent.setDisplayName(mainClass.getName());
serviceContent.scan(ClassUtils.getPackageName(mainClass));
serviceContent.setParent(parentContent);
serviceContent.setEnvironment(configurableEnvironment);
serviceContent.refresh();
parentContent = serviceContent;
}
}
List> list = properties.getClasses();
List beanFactories = new ArrayList<>();
if (!CollectionUtils.isEmpty(list))
{
StringBuilder sb = new StringBuilder();
ApplicationContext finalParentContent = parentContent;
list.stream().filter(aClass -> AnnotatedElementUtils.hasAnnotation(aClass, SpringBootApplication.class) && (null == mainClasses || !mainClasses.contains(aClass))).forEach(aClass ->
{
AnnotationConfigApplicationContext serviceContent = new AnnotationConfigApplicationContext();
serviceContent.setDisplayName(aClass.getName());
serviceContent.scan(ClassUtils.getPackageName(aClass));
serviceContent.setParent(finalParentContent);
serviceContent.setEnvironment(configurableEnvironment);
serviceContent.refresh();
// region 注册 Controller
Map mappingMap = serviceContent.getBeansWithAnnotation(Controller.class);
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Method getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);
mappingMap.forEach((key, handler) ->
{
if (context.containsBean(key))
{
return;
}
assert getMappingForMethod != null;
getMappingForMethod.setAccessible(true);
Class> handlerType = handler.getClass();
if (handlerType != null)
{
Class> userType = ClassUtils.getUserClass(handlerType);
Map methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup) method ->
{
try
{
return (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, method, userType);
}
catch (Throwable ex)
{
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
sb.append(formatMappings(userType, methods));
methods.forEach((method, mapping) ->
{
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
requestMappingHandlerMapping.registerMapping(mapping, handler, invocableMethod);
});
}
});
// endregion 注册 Controller
beanFactories.add(serviceContent.getBeanFactory());
});
for (ConfigurableListableBeanFactory beanFactory : beanFactories)
{
PaaSListableBeanFactory.putBeanFactory(beanFactory);
}
logger.info(sb.toString());
}
}
}
@Override
public void stop()
{
initialized.getAndSet(false);
}
@Override
public boolean isRunning()
{
return initialized.get();
}
@Override
public int getPhase()
{
return 10000;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy