`
joinhack
  • 浏览: 14724 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

ASM在Spring中的使用

阅读更多
上次我介绍了一下ASM大概情况请参见ASM详解
接着上次说得的我会介绍ASM在Spring中的一些使用,接触过spring的朋友都应该接触过ClassPathXmlApplicationContext或FileSystemXmlApplicationContext,他们都是加载spring配置文件形成spring应用上下文的类。
下面是ClassPathXmlApplicationContext与FileSystemXmlApplicationContext类关系。
                AbstractApplicationContext
                           /|\
                            |
            AbstractRefreshableApplicationContext
                           /|\
                            |
        AbstractRefreshableConfigApplicationContext
           /|\
                            |
                AbstractXmlApplicationContext
                  /|\                  /|\
                   |                    |
  ClassPathXmlApplicationContext    FileSystemXmlApplicationContext


在spring中设置扫描annotation的语句是:<context:component-scan base-package="com.appspot.coder9527.joinhack">,这样容器在启动的时候就会去扫描配置包对应的类,查看是否有annotation,如果有annotation的配置,spring容器就会根据annotation的描述完成bean的配置。在上述过程中使用到ASM的地方就是AbstractRefreshableApplicationContext的refreshBeanFactory方法,refreshBeanFactory方法调用loadBeanDefinitions方法完成bean定义loadBeanDefinitions中会调用XmlBeanDefinitionReader类的loadBeanDefinitions加载bean的定义.在这个过程中会调用到NamespaceHandlerSupport的parse方法,该方法通过配置寻找到对应的BeanDefinitionParser,上述的配置中spring会使用ComponentScanBeanDefinitionParser来完成bean定义,下面是ComponentScanBeanDefinitionParser的实现代码.
public BeanDefinition parse(Element element, ParserContext parserContext) {
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

return null;
}
在上述实现中值得注意的是ClassPathBeanDefinitionScanner类就是来扫描ClassPath中指定包对应的bean,在doScan方法中可以看到找到findCandidateComponents方法通过MetadataReaderFactory创建类的MetadataReader使用,MetadataReader来读取annotation,下面是MetadataReader的类结构。

                             MetadataReader
                                    /|\
                                     |
                           SimpleMetadataReader

ClassPathBeanDefinitionScanner中扫描所有的Class文件,使用SimpleMetadataReader获得ClassMetadata信息,下面是SimpleMetadataReader的代码.
final class SimpleMetadataReader implements MetadataReader {

private final Resource resource;
private final ClassMetadata classMetadata;
private final AnnotationMetadata annotationMetadata;

SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
InputStream is = resource.getInputStream();
ClassReader classReader = null;
try {
classReader = new ClassReader(is);
} finally {
is.close();
}

AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, true);

this.annotationMetadata = visitor;
// (since AnnotationMetadataReader extends ClassMetadataReadingVisitor)
this.classMetadata = visitor;
this.resource = resource;
}

public Resource getResource() {
return this.resource;
}

public ClassMetadata getClassMetadata() {
return this.classMetadata;
}

public AnnotationMetadata getAnnotationMetadata() {
return this.annotationMetadata;
}
}
到这里为止我们可以看到ASM相关代码ClassReader和Vistor。有兴趣的朋友可以继续读相关的源码。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics