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"); } }
相关推荐
LogParser 2.2安装文件LogParser 2.2安装文件LogParser 2.2安装文件
Spring Framework API文档。...它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IOC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transaction Management,等等......
使用开源mp4jar包实现mp4的切割和拼接
一个 读,写,创建MP4 容器的java API---mp4parser。github上面的一个开源项目。https://github.com/sannies/mp4parser
nested exception is java.lang.IllegalStateException: Context namespace element 'component-scan' and its parser class [org.springframework.context.annotation.ComponentScanBeanDefinitionParser] are ...
提供对Xml文件的解析功能,xml, parser
enju parser enju parser
javaParser 包 javaparser-core-3.6.16.jar,对java文件进行解析。修改。
php-apk-parser, 从. apk 文件读取有关应用程序的基本信息 Apk分析程序这个软件包可以提取应用程序包文件,以操作系统运行的设备使用的APK格式。 它可以打开一个APK文件并提取包含的清单文件来解析它,并检索它所...
编译原理lex词法分析 使用 parser generator , vc++工程实现
针对大数据内容采编挖搜的综合需求,融合了网络精准采集、自然语言理解、文本挖掘和语义搜索的最新研究成果,是大数据时代语义智能分析一大利器。
spring源码带注释的,直接可以阅读,不需要重新编译。
xml 文件解析 解析后放在数组中可以进行访问(还有一点小问题)
Groovy-JSON-Parser
ini-parser, 读/写INI文件的简便方法 ! INI文件分析器用于读取/写入来自 C# 流。文件流和写入的字符串的.NET 。Mono和rec兼容( * ) 库。也实现合并操作,对于完整的ini文件,部分,甚至是文件中包含的键的子集。( *...
刚开始解码H264视频时,查阅文档说有Nalu头,参考雷神代码,将文件指针传入去掉头可以解码,但是需要每次传入定量buffer解码,不是传入文件指针,经过修改可以用有bug
Excel Parser提供了一个功能,可以轻松地从Spring引导应用程序中提取Excel数据。 使用Apache POI库对API进行了抽象,并且通过使用Excel Parser,用户可以专注于编写业务逻辑。 同时支持DOM类型XSSFWorkBook和SAX...
把压缩文件解压到目录下,更新命名空间 $filename = 'benben.apk';//apk所在的路径地址 $apkParser = new Parser($filename); $apkParser->getManifest()->getPackageName(); //获取apk包名 $apkParser->...
Also, Learning Groovy 3 has been updated to Groovy 3.0 to include the new Parrot parser which was extended to support additional syntax options and language features. It also includes coverage of ...