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。有兴趣的朋友可以继续读相关的源码。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值