Spring使用groovy作为bean,官方用了lang标签,但都是一个个文件。Groovy本身编译成class文件后当然可以和Java完全一样可以被component-scan。
但是我想实现能够扫描groovy文件,并且groovy文件发生修改时候能够重新load(方便开发环境中提高效率),网上查查了,然后自己摸索了下,简单实现了。
思路:
1. 通过NamespaceHandlerSupport自己写一个parser,parser和已有的component-scan的区别就是修改了ClassPathBeanDefinitionScanner的reourceLoader,classloader用GroovyClassLoader,metadataReaderFactory重写了一个支持groovy class的,spring的是用asm去解析class文件(所以他也只支持编译后的)。
2. 写个timer监听groovy文件的最后修改时间,发生变化的,就让application context reload。
代码献上
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ComponentScanBeanDefinitionParser; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.stereotype.Component; import org.w3c.dom.Element; public class ComponentGroovyScanParser extends ComponentScanBeanDefinitionParser { @Override protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), true); scanner.setEnvironment(parserContext.getReaderContext().getEnvironment()); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class)); scanner.setResourceLoader(new PathMatchingResourcePatternResolver(ClassLoaderHolder.gcl)); scanner.setResourcePattern("**/*.groovy"); PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver( ClassLoaderHolder.gcl); scanner.setMetadataReaderFactory(new CachingMetadataReaderFactory2(resourcePatternResolver)); return scanner; } }
import java.io.IOException; import java.lang.annotation.Annotation; import java.util.LinkedHashMap; import java.util.Map; import org.springframework.asm.Opcodes; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; public class CachingMetadataReaderFactory2 extends SimpleMetadataReaderFactory { /** Default maximum number of entries for the MetadataReader cache: 256 */ public static final int DEFAULT_CACHE_LIMIT = 256; private volatile int cacheLimit = DEFAULT_CACHE_LIMIT; @SuppressWarnings("serial") private final Map<Resource, MetadataReader> metadataReaderCache = new LinkedHashMap<Resource, MetadataReader>( DEFAULT_CACHE_LIMIT, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry<Resource, MetadataReader> eldest) { return size() > getCacheLimit(); } }; /** * Create a new CachingMetadataReaderFactory for the default class loader. */ public CachingMetadataReaderFactory2() { super(); } /** * Create a new CachingMetadataReaderFactory for the given resource loader. * * @param resourceLoader * the Spring ResourceLoader to use (also determines the * ClassLoader to use) */ public CachingMetadataReaderFactory2(ResourceLoader resourceLoader) { super(resourceLoader); } /** * Create a new CachingMetadataReaderFactory for the given class loader. * * @param classLoader * the ClassLoader to use */ public CachingMetadataReaderFactory2(ClassLoader classLoader) { super(classLoader); } /** * Specify the maximum number of entries for the MetadataReader cache. * Default is 256. */ public void setCacheLimit(int cacheLimit) { this.cacheLimit = cacheLimit; } /** * Return the maximum number of entries for the MetadataReader cache. */ public int getCacheLimit() { return this.cacheLimit; } @Override public MetadataReader getMetadataReader(Resource resource) throws IOException { if (getCacheLimit() <= 0) { return super.getMetadataReader(resource); } synchronized (this.metadataReaderCache) { MetadataReader metadataReader = this.metadataReaderCache.get(resource); if (metadataReader == null) { metadataReader = genReader(resource); this.metadataReaderCache.put(resource, metadataReader); } return metadataReader; } } @SuppressWarnings("rawtypes") private MetadataReader genReader(final Resource resource) throws IOException { Class clz = ClassLoaderHolder.gcl.parseClass(resource.getFile()); final AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor( super.getResourceLoader().getClassLoader()); Class[] ll = clz.getInterfaces(); // must has GroovyObject String[] interfaces = new String[ll.length]; for (int i = 0; i < interfaces.length; i++) { interfaces[i] = ll[i].getName(); } visitor.visit(0, Opcodes.ACC_PUBLIC, clz.getName(), null, clz.getSuperclass().getName(), interfaces); Annotation[] ll2 = clz.getAnnotations(); if (ll2.length > 0) { for (Annotation ano : ll2) { visitor.getAnnotationTypes().add(ano.annotationType().getName()); } } MetadataReader reader = new MetadataReader() { @Override public Resource getResource() { return resource; } @Override public ClassMetadata getClassMetadata() { return visitor; } @Override public AnnotationMetadata getAnnotationMetadata() { return visitor; } }; return reader; } /** * Clear the entire MetadataReader cache, removing all cached class * metadata. */ public void clearCache() { synchronized (this.metadataReaderCache) { this.metadataReaderCache.clear(); } } }
import groovy.lang.GroovyClassLoader; public class ClassLoaderHolder { public static GroovyClassLoader gcl = new GroovyClassLoader(); static { gcl.addClasspath("src"); } }
相关推荐
nested exception is java.lang.IllegalStateException: Context namespace element 'component-scan' and its parser class [org.springframework.context.annotation.ComponentScanBeanDefinitionParser] are ...
1. **解析XML**:首先,使用XMLSlurper或XMLParser将XML字符串或文件转换为Groovy的DOM(文档对象模型)表示。例如: ```groovy def xml = new XmlSlurper().parseText('<xml><node>text</node></xml>') ``` 2. *...
通过mp4parser,我们可以轻松地处理这些任务,实现灵活的视频处理功能。 总的来说,mp4parser是一个强大的工具,它使得开发者无需深入理解MP4文件的复杂结构,也能有效地进行视频处理。在处理大量视频内容时,掌握...
通过阅读项目的官方文档和示例代码,你可以快速掌握如何利用MP4parser来处理MP4文件。此外,由于这是一个开源项目,你可以根据需要自定义和扩展它的功能,以满足特定的项目需求。 总之,MP4parser是一个强大的工具...
`javaparser-core-3.6.16.jar` 文件是 JavaParser 库的核心组件,包含了对 Java 语言解析所需的所有核心类和方法。 JavaParser 提供了对 Java 语法的深度理解,能够将源代码转换为抽象语法树(Abstract Syntax Tree...
Spring AOP 是基于 IOC 的 Bean 加载来实现的,本文主要介绍 Spring AOP 原理解析的切面实现过程。AOP 切面的实现是将切面类的所有切面方法根据使用的注解生成对应 Advice,并将 Advice 连同切入点匹配器和切面类等...
它提供了一种灵活的方式,通过SQL-like语法来查询和分析各种类型的文本日志文件,包括IIS日志、事件查看器日志、CSV文件等。下面将详细介绍LogParser 2.2的主要功能、特性以及安装过程。 **主要功能:** 1. **强大...
总之,SqlParser C++实现的SQL语法解释器是一个强大的工具,它通过词法分析和语法分析解析SQL语句,为数据库操作提供了基础。理解和掌握SqlParser的工作原理,对于开发和维护与数据库相关的软件系统具有重要意义。
XMLParser在iOS开发中是一种常用的解析XML数据的工具,它允许开发者将XML文件转换为可操作的数据结构,便于在iPhone应用程序中使用。XML(Extensible Markup Language)是一种标记语言,常用于存储和传输结构化数据...
Spring Framework API文档。...它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IOC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transaction Management,等等......
本主题聚焦于lex词法分析和parser generator的使用,结合VC++环境来实现编译器的构建。 **词法分析(Lex)** 词法分析,也称为扫描或Tokenizing,是编译器的第一个阶段。它的任务是将源代码分解成一系列的词素,...
通过正确地分割和解析NAL单元,我们可以确保FFmpeg的解码器能够正确解码H264视频流,即使在文件指针不直接提供完整NAL单元的情况下。这个过程需要对FFmpeg的API有深入理解,并能灵活应对各种输入数据格式的挑战。
Spring 框架是 Java 开发中的一个核心组件,它为构建可维护、模块化和松耦合的应用程序提供了一种强大的方式。...通过这些深入的学习,开发者可以更好地利用 Spring 框架来设计和实现高效、可扩展的 Java 应用程序。
NLPIR-Parser作为NLPIR工具包的一部分,可能包含了用于解析和处理文本的接口、库文件、示例代码等资源。用户可以通过这些资源,快速集成NLPIR的功能到自己的应用中,实现对大数据内容的高效处理和分析。 总的来说,...
sketch-node-parser, 使用纯NodeJS从草图中解析文件 sketch-node-parser使用纯NodeJS从草图中解析文件。这个项目只是一个 proof-of-concept,并没有准备好使用。摘要这个程序演示如何打开一个草图文件,并将它解析为...
"apk-parser"就是一个强大的Java库,专用于解析APK文件,揭示其隐藏的元数据。本文将详细介绍apk-parser的使用方法和核心功能。 apk-parser是一个高效且全面的APK解析库,它的主要目标是帮助开发者和安全研究人员...
MP4 Parser是一种强大的工具,专门用于处理和解析MP4格式的视频文件。MP4(MPEG-4 Part 14)是广泛应用于互联网上的多媒体容器格式,它能包含视频、音频、字幕、图像等多种媒体类型。在进行视频编辑时,理解并利用...
值得注意的是,描述中提到了一个链接(http://blog.csdn.net/xiaodao1986/archive/2009/07/24/4378135.aspx),这可能提供了关于`table_parser`类更详细的实现和使用说明。在实际应用中,查看这个博客文章会帮助理解...
Spring IOC(Inversion of Control)容器是一种设计模式,用于实现对对象创建和依赖关系管理的反转。通过这种方式,Spring容器负责创建对象,并将它们之间的依赖关系自动配置好,而不是由应用程序代码来完成这些工作。...
通过实现`org.springframework.beans.factory.xml.NamespaceHandler`接口,我们可以定义自己的处理逻辑,将自定义标签转换为Spring能够理解的Bean定义。 `spring-web-namespacehandler`通常包含Spring MVC相关的...