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

io.foodtechlab.domainbeans.RCoreRegistar Maven / Gradle / Ivy

package io.foodtechlab.domainbeans;

import com.rcore.domain.commons.usecase.UseCase;
import com.rcore.event.driven.EventHandler;
import lombok.Setter;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Setter
@Log
@SuppressWarnings("SpellCheckingInspection")
class RCoreRegistar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware, PriorityOrdered {
    private ResourceLoader resourceLoader;
    private Environment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map attrs = Objects.requireNonNull(metadata.getAnnotationAttributes(EnableRCoreSpring.class.getName()));

        LinkedHashSet candidateComponents = new LinkedHashSet<>();
        ClassPathScanningCandidateComponentProvider scanner = getScanner(attrs);
        long start = System.currentTimeMillis();
        for (String basePackage : getBasePackages(attrs, metadata.getClassName())) {
            candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
        }
        log.info("Scanning taking " + (System.currentTimeMillis() - start) + "");
        start = System.currentTimeMillis();
        for (BeanDefinition candidateComponent : candidateComponents) {
            if (alreadyExist(registry, candidateComponent)) // Не будем регать кейс если он у нас где-то в конфиге прописан
                continue;

            String beanClassName = getDefinitionClassName(candidateComponent);
            registry.registerBeanDefinition(beanClassName, candidateComponent);
        }
        log.info("Register definition taking " + (System.currentTimeMillis() - start));
    }


    protected ClassPathScanningCandidateComponentProvider getScanner(Map attrs) {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false, this.environment);

        scanner.addIncludeFilter(new AssignableTypeFilter(UseCase.class));
        scanner.addIncludeFilter(new AssignableTypeFilter(EventHandler.class));

        for (Class toBean : ((Class[]) attrs.get("anotherDomainBeans"))) {
            scanner.addIncludeFilter(new AssignableTypeFilter(toBean));
        }

        scanner.setResourceLoader(this.resourceLoader);

        return scanner;
    }


    protected Set getBasePackages(Map attributes, String className) {
        Set basePackages = new HashSet<>();
        for (String pkg : (String[]) attributes.get("value")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (String pkg : (String[]) attributes.get("basePackages")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (Class clazz : (Class[]) attributes.get("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }

        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(className));
        }
        return basePackages;
    }

    /**
     * Небольшой костыль, не будет регистрировать бины, которые уже определенны в спринге
     */
    private boolean alreadyExist(BeanDefinitionRegistry registry, BeanDefinition definition) {
        String[] candidates = registry.getBeanDefinitionNames();
        for (String candidate : candidates) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(candidate);
            if (isSameClass(beanDefinition, definition)) {
                return true;
            }
        }
        return false;
    }

    private boolean isSameClass(BeanDefinition d1, BeanDefinition d2) {
        return Objects.equals(getDefinitionClassName(d1), getDefinitionClassName(d2));
    }

    private String getDefinitionClassName(BeanDefinition definition) {
        String className = definition.getBeanClassName();

        if (className != null)
            return className;

        if (definition instanceof AnnotatedBeanDefinition) { // definition with @Bean Annotation cause this issue
            MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition).getFactoryMethodMetadata();
            if (factoryMethodMetadata != null) {
                className = factoryMethodMetadata.getReturnTypeName();
            }
        }

        return className;
    }

    // Выполним после того, как прочекаем все остальные конфиги
    // Чтобы этот регистер импортировал бины, которые НЕ ОПРЕДЕЛЕННЫ вручную
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy