- step1
读取添加了@ComponentScan注解的类,进而读取被添加了@Component注解,且需要被扫描的类。
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);
if(componentScan!=null){
//打印注解上添加的basePackages属性
for(String p:componentScan.basePackages()){
System.out.println(p);
//将目录转为路径
//com.itheima.a05.component -> classpath*:com/itheima/a05/component/**/*.class
String path="classpath*:"+p.replace(".","/")+"/**/*.class";
final Resource[] resources = context.getResources(path);
}
- step2
使用step1读取到的元信息来构建Bean定义
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);
if(componentScan!=null){
//打印注解上添加的basePackages属性
for(String p:componentScan.basePackages()){
System.out.println(p);
//将目录转为路径
//com.itheima.a05.component -> classpath*:com/itheima/a05/component/**/*.class
String path="classpath*:"+p.replace(".","/")+"/**/*.class";
final Resource[] resources = context.getResources(path);
CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
//Resources是二进制字节码
for(Resource resource:resources){
System.out.println("resource: "+resource);
MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
metadataReader.getClassMetadata().getClassName();
System.out.println(metadataReader.getAnnotationMetadata());
}
}
}
- 将Bean定义加入BeanFactory
beanFactory.registerBeanDefinition(name, bd);
- 完整代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import java.io.IOException;
public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override // context.refresh
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
try {
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if (componentScan != null) {
for (String p : componentScan.basePackages()) {
System.out.println(p);
// com.itheima.a05.component -> classpath*:com/itheima/a05/component/**/*.class
String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
System.out.println(path);
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource : resources) {
// System.out.println(resource);
MetadataReader reader = factory.getMetadataReader(resource);
// System.out.println("类名:" + reader.getClassMetadata().getClassName());
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
// System.out.println("是否加了 @Component:" + annotationMetadata.hasAnnotation(Component.class.getName()));
// System.out.println("是否加了 @Component 派生:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
if (annotationMetadata.hasAnnotation(Component.class.getName())
|| annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
AbstractBeanDefinition bd = BeanDefinitionBuilder
.genericBeanDefinition(reader.getClassMetadata().getClassName())
.getBeanDefinition();
String name = generator.generateBeanName(bd, beanFactory);
beanFactory.registerBeanDefinition(name, bd);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 使用自定义后处理器
public static void main(String[] args) throws IOException {
// GenericApplicationContext 是一个【干净】的容器
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
context.registerBean(ComponentScanPostProcessor.class); // 解析 @ComponentScan
}