• 聊聊、Spring自动扫描器


    一、项目

     二、自定义注解

    package org.rockcode.annotations;

    import java.lang.annotation.*;

    @Target(ElementType.TYPE)

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface EnableFruit {

      String name() default "EnableFruit";

    }

    三、services 目录 

    package org.rockcode.services;

    public interface Fruit {

    public String getName();

    }

      

    package org.rockcode.services;

    import org.rockcode.annotations.EnableFruit;

    @EnableFruit

    public class Apple implements Fruit{

    @Override public String getName() {

    return "Apple";

    }

    }

     三、扫描services目录下面@EnableFruit的类 

    public class ClassPathEnableEnumScanner {
    
    //解析路径下的 class
    private static final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    //转换成 MetaData 读取类
    private static final SimpleMetadataReaderFactory register = new SimpleMetadataReaderFactory();
    
    public static void getClazzFromAnnotation(String pkgPath, Class<? extends Annotation> annotationClass) {
    
    //获取spring的包路径
    String pathPackage = "classpath*:org/rockcode/services/**/*.class";
    
    // 返回的是 FileSystemResource 数组
    // file [E:ideaSpringIOC	argetclassesorg
    ockcodeservicesApple.class]
    // file [E:ideaSpringIOC	argetclassesorg
    ockcodeservicesBanana.class]
    // file [E:ideaSpringIOC	argetclassesorg
    ockcodeservicesFruit.class]
    // file [E:ideaSpringIOC	argetclassesorg
    ockcodeservicesOrange.class]
    Resource[] resources = new Resource[0];
    try {
    //加载路径下的资源
    resources = resolver.getResources(pathPackage);
    } catch (IOException e) {
    
    }
    for (int i = 0; i < resources.length; i++) {
    Resource resource = resources[i];
    
    MetadataReader metadataReader = null;
    try {
    //读取资源
    // 返回 classMetadata annotationMetadata
    metadataReader = register.getMetadataReader(resource);
    } catch (IOException e) {
    continue;
    }
    
    //读取资源的注解配置
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    
    //判断是否包含注解,如果有则继续,没有就重新遍历
    if (!annotationMetadata.hasAnnotation(annotationClass.getName())) continue;
    
    //类信息
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    
    //类全名
    String className = classMetadata.getClassName();
    try {
    //加载类
    Class<?> clazz = Class.forName(className);
    // 这里的逻辑是注册到 beanDefinitionMap,实现方式很多,通过 clazz 实例化对象,调用相关方法,等等
    // todo
    
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }
    }
    
    public static void main(String[] args) {
    getClazzFromAnnotation("org.rockcode.services", EnableFruit.class);
    }
    }

      

    四、通过继承 ClassPathBeanDefinitionScanner 实现扫描器

    在 Spring 体系中,ClassPathBeanDefinitionScanner 占有很重要的地位,如果要实现无 xml 化,就需要注解,有注解就需要自动扫描器。

    package org.rockcode.scanner;
    
    import org.rockcode.annotations.EnableFruit;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
    import org.springframework.context.support.GenericApplicationContext;
    import org.springframework.core.type.filter.AnnotationTypeFilter;
    
    public class MyClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
    
        public MyClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry){
            super(registry,false);
        }
    
        public void registerTypeFilter(){
            addIncludeFilter(new AnnotationTypeFilter(EnableFruit.class));
        }
    
        public static void main(String[] args) {
            GenericApplicationContext context = new GenericApplicationContext();
            MyClassPathBeanDefinitionScanner myClassPathBeanDefinitionScanner = new MyClassPathBeanDefinitionScanner(context);
            myClassPathBeanDefinitionScanner.registerTypeFilter();
            myClassPathBeanDefinitionScanner.scan("org.rockcode.services");
            // 启动容器,也就是将扫描到的class实例化,并注册到beanFactory中,存入beanDefinitionMap
            context.refresh();
            //这里会拿到所有的bean实例
                    String[] beanDefinitionNames = context.getBeanDefinitionNames();
            for (String beanDefinitionName : beanDefinitionNames) {
                System.out.println(context.getBean(beanDefinitionName));
            }
        }
    }
  • 相关阅读:
    [ jquery 选择器 总览 ] jquery选择器总览
    [ jquery 选择器 :empty ] 此方法选取所有不包含子元素或者文本的空元素
    [ jquery 选择器 :contains(text) ] 此方法选取包含给定文本的元素
    [ jquery 选择器 :header ] 此方法选取匹配如 h1, h2, h3之类的标题元素
    [ jquery 选择器 :last ] 此方法选取jquery对象中的最后一个对象
    [ jquery 选择器 :gt(index) ] 此方法选取匹配大于指定索引值的所有元素
    [ jquery 选择器 :lt(index) ] 此方法选取匹配小于指定索引值的所有元素
    [ jquery 选择器 :eq(index) ] 此方法精确选取指定jquery对象中的指定下角标的对象
    剑指Offer 35 复杂链表的复制 && LeetCode 138 复制带随机指针的链表 哈希
    LeetCode 102. 二叉树的层序遍历 && 剑指 Offer 32
  • 原文地址:https://www.cnblogs.com/xums/p/12377256.html
Copyright © 2020-2023  润新知