上次我介绍了一下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。有兴趣的朋友可以继续读相关的源码。
接着上次说得的我会介绍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。有兴趣的朋友可以继续读相关的源码。