Spring下掃描特定包下特定註解的類並動態註冊bean

xbynet發表於2017-03-28
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> T getBean(Class<T> clz){
        return context.getBean(clz);
    }
    public static <T> T getBean(String name , Class<T> 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<Class<?>> scan(String[] confPkgs, Class<? extends Annotation>... annotationTags){
        Set<Class<?>> resClazzSet = new HashSet<>();
        List<AnnotationTypeFilter> typeFilters = new LinkedList<>();
        if (ArrayUtils.isNotEmpty(annotationTags)){
            for (Class<? extends Annotation> 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<Class<?>> 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<AnnotationTypeFilter> 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;
    }
}

相關文章