资讯专栏INFORMATION COLUMN

Spring下扫描特定包下特定注解的类并动态注册bean

vibiu / 920人阅读

摘要:动态注册扫描提取包路径下,标记了注解的类出现异常注册检查当前扫描到的类是否含有任何一个指定的注解标记过滤匹配类型时出错

public class SpringContextHolder implements ApplicationContextAware{

    private static ApplicationContext context;
    private static BeanDefinitionRegistry beanDefinitonRegistry;

    public static ApplicationContext getApplicationContext() {
        return context;
    }
    public static Object getBean(String name){
        return context.getBean(name);
    }
    public static  T getBean(Class clz){
        return context.getBean(clz);
    }
    public static  T getBean(String name , Class clz){
        return context.getBean(name, clz);
    }
    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
      //DefaultListableBeanFactory acf = (DefaultListableBeanFactory) app.getAutowireCapableBeanFactory();
      ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
        beanDefinitonRegistry = (BeanDefinitionRegistry) configurableApplicationContext
          .getBeanFactory();
    }
    /**
     * 动态注册bean
     * @param beanName
     * @param beanDefinition
     */
    public synchronized static void registerBean(String beanName, BeanDefinition beanDefinition){
        //DefaultListableBeanFactory beanDefinitonRegistry = (DefaultListableBeanFactory) app.getAutowireCapableBeanFactory();
        if(!beanDefinitonRegistry.containsBeanDefinition(beanName)){
          beanDefinitonRegistry.registerBeanDefinition(beanName, beanDefinition);
        }
    }
    public static void registerBean(BeanDefinition beanDefinition){
        //DefaultListableBeanFactory beanDefinitonRegistry = (DefaultListableBeanFactory) app.getAutowireCapableBeanFactory();
        String simpleNameString=beanDefinition.getBeanClassName();
        if(simpleNameString.contains(".")){
            simpleNameString=simpleNameString.substring(simpleNameString.lastIndexOf(".")+1);
        }
        simpleNameString=StringUtil.lowerFirstChar(simpleNameString);
        registerBean(simpleNameString,beanDefinition);
    }
    public static BeanDefinitionBuilder getBeanDefinitionBuilder(Class clazz){
        return BeanDefinitionBuilder.genericBeanDefinition(clazz);
    }

}
public class ClassScanner {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final String RESOURCE_PATTERN = "**/%s/**/*.class";
    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    public ClassScanner(){
    }

    @SafeVarargs
    public final Set> scan(String[] confPkgs, Class... annotationTags){
        Set> resClazzSet = new HashSet<>();
        List typeFilters = new LinkedList<>();
        if (ArrayUtils.isNotEmpty(annotationTags)){
            for (Class annotation : annotationTags) {
                typeFilters.add(new AnnotationTypeFilter(annotation, false));
            }
        }
        if (ArrayUtils.isNotEmpty(confPkgs)) {
            for (String pkg : confPkgs) {
                String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX  + String.format(RESOURCE_PATTERN,ClassUtils.convertClassNameToResourcePath(pkg));
                try {
                    Resource[] resources = this.resourcePatternResolver.getResources(pattern);
                    MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
                    for (Resource resource : resources) {
                        if (resource.isReadable()) {
                            MetadataReader reader = readerFactory.getMetadataReader(resource);
                            String className = reader.getClassMetadata().getClassName();
                            if (ifMatchesEntityType(reader, readerFactory,typeFilters)) {
                                Class curClass = Thread.currentThread().getContextClassLoader().loadClass(className);
                                resClazzSet.add(curClass);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("扫描提取[{}]包路径下,标记了注解[{}]的类出现异常", pattern,StringUtils.join(typeFilters,","));
                }
            }
        }
        return resClazzSet;
    }

    /**
     * 注册Bean
     * @param classList
     */
    public void regist(List> classList){
        for(Class clzz:classList){
            SpringContextHolder.registerBean(SpringContextHolder.getBeanDefinitionBuilder(clzz).getBeanDefinition());
        }
    }

    /**
     * 检查当前扫描到的类是否含有任何一个指定的注解标记
     * @param reader
     * @param readerFactory
     * @return ture/false
     */
    private boolean ifMatchesEntityType(MetadataReader reader, MetadataReaderFactory readerFactory,List typeFilters) {
        if (!CollectionUtils.isEmpty(typeFilters)) {
            for (TypeFilter filter : typeFilters) {
                try {
                    if (filter.match(reader, readerFactory)) {
                        return true;
                    }
                } catch (IOException e) {
                    logger.error("过滤匹配类型时出错 {}",e.getMessage());
                }
            }
        }
        return false;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66900.html

相关文章

  • Spring详解3.Bean的装配

    摘要:的依赖关系,根据依赖关系配置完成之间的装配。的行为信息,如生命周期范围及生命周期各过程的回调函数。使用该种装配模式时,优先匹配参数最多的构造函数。如果提供了默认的构造函数,则采用否则采用进行自动装配。 点击进入我的博客 1 Spring容器与Bean配置信息 Bean配置信息 Bean配置信息是Bean的元数据信息,它由一下4个方面组成: Bean的实现类 Bean的属性信息,如数...

    endiat 评论0 收藏0
  • 看起来很长但还是有用的Spring学习笔记

    摘要:关于依赖注入注入的注解提供的注解不仅仅是对象,还有在构造器上,还能用在属性的方法上。与之相反,的限定符能够在所有可选的上进行缩小范围的操作,最终能够达到只有一个满足所规定的限制条件。注解是使用限定符的主要方式。 本文首发于泊浮目的专栏:https://segmentfault.com/blog... Spring致力于提供一种方法管理你的业务对象。在大量Java EE的应用中,随处可...

    DTeam 评论0 收藏0
  • 3.1、定义一个控制器:使用 @Controller 和 @RequestMapping

    摘要:用定义一个控制器注解指定一个特定的类担任控制器的角色。典型地,类级别的注解映射一个指定的请求路径或者是路径匹配模式到一个控制器,使用额外的方法层注解缩小主要映射的范围。第一处是类级别的,它指出这个控制器中的所有方法都与路径相关。 1)用 @Controller 定义一个控制器     注解 @Controller 指定一个特定的类担任控制器的角色。Spring 不要求你集成任何控制器基...

    Render 评论0 收藏0
  • Spring 各种注解备注

    摘要:注解,以明确指出该类是配置的信息源注解会告知扫描指定的包来初始化这能够确保我们声明的能够被发现。注解加载配置文件禁用特定的自动配置注解等价于以默认属性使用,和。使用这个注释将警告信息去掉。 @ConditionalOnBean 配置了某个特定Bean@ConditionalOnMissingBean 没有配置特定的Bean@ConditionalOnClass Classpath里有指...

    hosition 评论0 收藏0
  • springmvc常用注解标签详解

    摘要:分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了注解。作用该注解用于将的方法返回的对象,通过适当的转换为指定格式后,写入到对象的数据区。用于注解层,在类上面注解。使用标记的参数。 1、@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个M...

    notebin 评论0 收藏0

发表评论

0条评论

vibiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<