解析class文件,读取类元信息
package cn.java.demo.beantag.internal.metareader;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FooOneService extends FooOneSuper0 implements FooOneInterface, FooTwoInterface {
public void method0() {
}
public void method1() {
/**
* 内部类
*/
@Data
class FooOneMemberClazz2 {
private Integer id;
}
}
/**
* 成员类
*/
@Data
public class FooOneMemberClazz0 {
private Integer id;
}
/**
* 内部类
*/
@Data
public static class FooOneMemberClazz1 {
private Integer id;
}
}
class FooOneSuper0 {
}
interface FooOneInterface {
}
interface FooTwoInterface {
}
package cn.java.demo.beantag.internal.metareader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import java.io.IOException;
import java.util.Set;
/**
* @date 2020-12-11 15:45
*/
@Slf4j
public class ClassPathScanningCandidateComponentProviderTest {
public static void main(String[] args) {
new ClassPathScanningCandidateComponentProviderTest().findCandidateComponents(null);
}
/**
* org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents()
*/
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
ResourceLoader resourceLoader = null;
ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(FooOneService.class.getName()) + ClassUtils.CLASS_FILE_SUFFIX;
log.info("packageSearchPath = {}", packageSearchPath);
try {
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath); // 查找所有资源
log.info("resources length = {}", resources.length);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
// getAnnotationMetadata 获取注解元信息
{
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
// ((不是内部类or是static的内部类) && ((不是接口&不是抽象) || (是抽象的&有方法配置@Lookup注解)))
boolean isCandidateComponent = (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
log.info("isCandidateComponent = {}", isCandidateComponent);
}
// getClassMetadata 获取类元信息
{
ClassMetadata classMetadata = metadataReader.getClassMetadata();
String className = classMetadata.getClassName(); // 类名
log.info("className = {}", className);
String superClassName = classMetadata.getSuperClassName(); // 父类
log.info("superClassName = {}", superClassName);
String[] interfaceNames = classMetadata.getInterfaceNames(); // 接口
if(!ObjectUtils.isEmpty(interfaceNames)){
for (String interfaceName : interfaceNames) {
log.info("interfaceName = {}", interfaceName);
}
}
String[] memberClassNames = classMetadata.getMemberClassNames(); // 成员类
for (String memberClassName : memberClassNames) {
log.info("memberClassName = {}", memberClassName);
MetadataReader memberClassMetadataReader = metadataReaderFactory.getMetadataReader(memberClassName);
ClassMetadata memberClassMetadata = memberClassMetadataReader.getClassMetadata();
String memberClassEnclosingClassName = memberClassMetadata.getEnclosingClassName();
log.info("\tenclosingClassName = {}", memberClassEnclosingClassName);
}
// the underlying class is an inner/nested class or a local class within a method // 外部类名
String enclosingClassName = classMetadata.getEnclosingClassName();
log.info("enclosingClassName = {}", enclosingClassName);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(basePackage); // 转换路径
}
}
输出
2020-12-11 16:28:11,071 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - packageSearchPath = classpath*:cn/java/demo/beantag/internal/metareader/FooOneService.class
2020-12-11 16:28:11,078 DEBUG [org.springframework.core.io.support.PathMatchingResourcePatternResolver] - Resolved classpath location [cn/java/demo/beantag/internal/metareader/FooOneService.class] to resources [URL [file:/Users/qudian/Documents/java_workspace/java_openstack_debug/springFrameworkDebug/web-demo/WebRoot/WEB-INF/classes/cn/java/demo/beantag/internal/metareader/FooOneService.class]]
2020-12-11 16:28:11,078 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - resources length = 1
2020-12-11 16:28:11,091 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - isCandidateComponent = true
2020-12-11 16:28:11,091 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - className = cn.java.demo.beantag.internal.metareader.FooOneService
2020-12-11 16:28:11,091 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - superClassName = cn.java.demo.beantag.internal.metareader.FooOneSuper0
2020-12-11 16:28:11,092 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - interfaceName = cn.java.demo.beantag.internal.metareader.FooOneInterface
2020-12-11 16:28:11,092 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - interfaceName = cn.java.demo.beantag.internal.metareader.FooTwoInterface
2020-12-11 16:28:11,092 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - memberClassName = cn.java.demo.beantag.internal.metareader.FooOneService$FooOneMemberClazz1
2020-12-11 16:28:11,094 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - enclosingClassName = cn.java.demo.beantag.internal.metareader.FooOneService
2020-12-11 16:28:11,094 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - memberClassName = cn.java.demo.beantag.internal.metareader.FooOneService$FooOneMemberClazz0
2020-12-11 16:28:11,094 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - enclosingClassName = cn.java.demo.beantag.internal.metareader.FooOneService
2020-12-11 16:28:11,094 INFO [cn.java.demo.beantag.internal.metareader.ClassPathScanningCandidateComponentProviderTest] - enclosingClassName = null