完成此任务有一个扫描包功能的类:
public class BaseClassScanUtils {
//设置资源规则
private static final String RESOURCE_PATTERN = "/**/*.class";
public static Map<String, Class> scanMyComponentAnnotation(String basePackage) {
//创建容器存储使用了指定注解的Bean字节码对象
Map<String, Class> annotationClassMap = new HashMap<String, Class>();
//spring工具类,可以获取指定路径下的全部类
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(basePackage) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
//MetadataReader 的工厂类
MetadataReaderFactory refractory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
//用于读取类信息
MetadataReader reader = refractory.getMetadataReader(resource);
//扫描到的class
String classname = reader.getClassMetadata().getClassName();
Class<?> clazz = Class.forName(classname);
//判断是否属于指定的注解类型
if(clazz.isAnnotationPresent(MyComponent.class)){
//获得注解对象
MyComponent annotation = clazz.getAnnotation(MyComponent.class);
//获得属value属性值
String beanName = annotation.value();
//判断是否为""
if(beanName!=null&&!beanName.equals("")){
//存储到Map中去
annotationClassMap.put(beanName,clazz);
continue;
}
//如果没有为"",那就把当前类的类名作为beanName
annotationClassMap.put(clazz.getSimpleName(),clazz);
}
}
} catch (Exception exception) {
}
return annotationClassMap;
}
public static void main(String[] args) {
//扫描的包的范围是:com.itheima
Map<String, Class> stringClassMap = scanMyComponentAnnotation("com.itheima");
System.out.println(stringClassMap);
}
}
第一步:创建一个注解
第二步:写一个类并实现BeanDefinitionRegistryPostProcessor接口
public class MyComponentBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
//通过扫描工具去扫描指定包及其子包下的所有类,收集使用@MyComponent的注解的;类
Map<String, Class> myComponentAnnotationMap = BaseClassScanUtils.scanMyComponentAnnotation("com.itheima");
//遍历Map,组装BeanDefinition进行注册
myComponentAnnotationMap.forEach((beanName,clazz)->{
//获得beanClassName
String beanClassName=clazz.getName();//用了此注解的类路径
//创建BeanDefinition
BeanDefinition beanDefinition=new RootBeanDefinition();
beanDefinition.setBeanClassName(beanClassName);
//注册
beanDefinitionRegistry.registerBeanDefinition(beanName,beanDefinition);
});
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
第三步:将实现接口的类放入application中:
<bean class="com.itheima.processor.MyComponentBeanFactoryPostProcessor"/>
第四步:创建任意类并使用创建的注解:
第五步:测试
public class ApplicationContextTest {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
OtherBean OtherBean = applicationContext.getBean(OtherBean.class);
System.out.println(OtherBean);
}
}
打印结果如下: