All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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