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

com.github.datalking.context.annotation.ConfigurationClassParser Maven / Gradle / Ivy

The newest version!
package com.github.datalking.context.annotation;

import com.github.datalking.annotation.Bean;
import com.github.datalking.annotation.ComponentScan;
import com.github.datalking.annotation.Import;
import com.github.datalking.annotation.meta.AnnotationAttributes;
import com.github.datalking.annotation.meta.AnnotationMetadata;
import com.github.datalking.annotation.meta.MethodMetadata;
import com.github.datalking.annotation.meta.StandardAnnotationMetadata;
import com.github.datalking.beans.factory.config.AnnotatedBeanDefinition;
import com.github.datalking.beans.factory.config.BeanDefinition;
import com.github.datalking.beans.factory.config.BeanDefinitionHolder;
import com.github.datalking.beans.factory.support.BeanDefinitionRegistry;

import java.lang.annotation.Annotation;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yaoo on 4/13/18
 */
public class ConfigurationClassParser {

    private final BeanDefinitionRegistry registry;

    private final ComponentScanAnnotationParser componentScanParser;

    private final Map configurationClasses = new LinkedHashMap<>();


    public ConfigurationClassParser(BeanDefinitionRegistry registry) {
        this.registry = registry;
        this.componentScanParser = new ComponentScanAnnotationParser(registry);

    }

    public void parse(Set configCandidates) {

        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();

            if (bd instanceof AnnotatedBeanDefinition) {
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }

        }

    }

    private void parse(AnnotationMetadata metadata, String beanName) {
        processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }

    protected final void parse(Class clazz, String beanName) {
        processConfigurationClass(new ConfigurationClass(clazz, beanName));
    }

    private void processConfigurationClass(ConfigurationClass configClass) {

        // ==== 真正扫描@Configuration、@Bean、@ComponentScan
        doProcessConfigurationClass(configClass);

        // 存储扫描结果
        this.configurationClasses.put(configClass, configClass);

    }


    /**
     * 扫描@ComponentScan、@Bean
     *
     * @param configClass 标注有@Configuration的类的元信息
     */
    private void doProcessConfigurationClass(ConfigurationClass configClass) {

        // ==== 如果configClass标注有@ComponentScan,则获取注解的属性map
//        Set componentScans = attributesForRepeatable(configClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        Set componentScans = attributesForRepeatable(configClass.getMetadata(), null, ComponentScan.class);

        if (!componentScans.isEmpty()) {
            for (AnnotationAttributes componentScan : componentScans) {

                // 通过ComponentScanAnnotationParser解析@ComponentScan注解
                Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, configClass.getMetadata().getClassName());

//                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
//
//                    AbstractBeanDefinition bd = (AbstractBeanDefinition) holder.getBeanDefinition();
//
//                    Class clazz = ((AbstractAutowireCapableBeanFactory) registry).doResolveBeanClass(bd);
//
//                    // 将配置的各个包下的Component类扫描出来 full lite  todo递归中止条件
//                    if (clazz.isAnnotationPresent(Component.class)) {
//                        parse(clazz, holder.getBeanName());
//                    }
//
//                }
            }
        }


        Set imports = getImports(configClass);
        // 循环处理注解中含有@import的注解
        processImports(configClass, imports);


        // 循环处理注解中含有@import的类
        //processImports(configClass, getImports(configClass), true);

        // ==== 扫描@Bean
        Set beanMethods = retrieveBeanMethodMetadata(configClass);

        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }


    }

    private void processImports(ConfigurationClass configClass, Collection importCandidates) {

        if (importCandidates.isEmpty()) {
            return;
        }

        for (ConfigurationClass c : importCandidates) {
            Class curClass = ((StandardAnnotationMetadata) c.getMetadata()).getIntrospectedClass();
            ImportBeanDefinitionRegistrar obj = null;
            if (ImportBeanDefinitionRegistrar.class.isAssignableFrom(curClass)) {
                try {
                    obj = (ImportBeanDefinitionRegistrar) curClass.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            // 将@Import的class加入configClass的map
            configClass.addImportBeanDefinitionRegistrar(obj, c.getMetadata());

        }


    }


    private Set getImports(ConfigurationClass confClass) {
        Set imports = new LinkedHashSet<>();
        Set visited = new LinkedHashSet<>();

        Annotation[] annos = confClass.getMetadata().getAnnotations();

        Deque stack = new ArrayDeque<>();
        for (Annotation annotation : annos) {
            AnnoClassTuple2 annoClass = new AnnoClassTuple2(annotation, ((StandardAnnotationMetadata) confClass.getMetadata()).getIntrospectedClass());
            stack.push(annoClass);
        }
//        stack.addAll(Arrays.asList(annos));

        while (!stack.isEmpty()) {
            AnnoClassTuple2 ac = stack.pop();

            Class annoTypeClass = ac.getAnnotation().annotationType();

            if (annoTypeClass.getName().equals(Import.class.getName())) {

                Class[] importedClass = ac.getClazz().getAnnotation(Import.class).value();

                for (Class c : importedClass) {
                    imports.add(new ConfigurationClass(c, c.getSimpleName()));
                }

            } else {
                visited.add(annoTypeClass);

                Annotation[] annos2 = annoTypeClass.getAnnotations();
                for (Annotation a : annos2) {
                    AnnoClassTuple2 ac2 = new AnnoClassTuple2(a, annoTypeClass);
                    if (!visited.contains(a.annotationType()) && !stack.contains(ac2)) {
                        stack.push(ac2);

                    }
                }

            }

        }

//        collectImports(confClass, imports, visited);
        return imports;
    }


//    private void collectImports(ConfigurationClass configClass, Set imports, Set visited) {
//
//        if (visited.add(configClass)) {
//
//            for (ConfigurationClass annotation : configClass.getAnnotations()) {
//
//                String annName = annotation.getMetadata().getClassName();
//                if (!annName.equals(Import.class.getName()) && !annName.startsWith("java")) {
//                    collectImports(annotation, imports, visited);
//                }
//            }
//
//            imports.addAll(configClass.getAnnotationAttributes(Import.class.getName(), "value"));
//        }
//
//    }

    private Set retrieveBeanMethodMetadata(ConfigurationClass configClass) {

        AnnotationMetadata original = configClass.getMetadata();
        Set beanMethods = original.getAnnotatedMethods(Bean.class);
        return beanMethods;


    }

    public Set getConfigurationClasses() {
        return this.configurationClasses.keySet();
    }


    private Set attributesForRepeatable(AnnotationMetadata metadata,
                                                              Class containerClass,
                                                              Class annotationClass) {

        //String containerClassName = containerClass.getName();
        // String annotationClassName = annotationClass.getName();

        Set result = new LinkedHashSet<>();

        AnnotationAttributes attrMap = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClass, false));
        if (attrMap != null) {
            result.add(attrMap);
        }


        //Map container = metadata.getAnnotationAttributes(containerClassName,false);

//        if (container != null && container.containsKey("value")) {
//            for (Map containedAttributes : (Map[]) container.get("value")) {
//                result.add(AnnotationAttributes.fromMap(containedAttributes));
//            }
//        }

        return result;
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy