手动实现一个@Component,讲一讲Spring的工厂后处理器
- 引子
- 需求
- 代码分析
- Spring工厂后处理器
引子
痛定思痛,主要问题出现在自己雀氏不熟悉框架底层、一些面试题,以及sql的一些情况淡忘了。
本章节的开始是对于过去的重新回顾,当然,我也会深入基础,阅读源码,仔细熟悉开发过程,对问题进行整体学习,
后面会深入去做一些sql的题目来提升mysql能力
相关代码代码和笔记已经放到了gitee中去,喜欢的读者记得点赞下载
链接: MyComponentAnnotation
需求
- 自定义一个注解,使用在类/方法上
- 可以通过包扫描工具(ComponetScan)完成对包扫描
- 通过工厂后处理器完成注解解析
- 通过BeanFactory可以获取到响应的Bean
代码分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
String value() default "";
}
@Component
public class MyComponentBeanFactory implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Map<String, Class> stringClassMap = BaseClassScanUtils.scanMyComponentAnnotation("com.Iron");
stringClassMap.forEach((a,b)->{
System.out.println(b.getName());
BeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName(b.getName());
registry.registerBeanDefinition(b.getName(), beanDefinition);
});
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
@MyComponent("myTestBean")
public class TestBean1 {
}
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) {
Map<String, Class> stringClassMap = scanMyComponentAnnotation("com.Iron");
System.out.println(stringClassMap);
}
}
public class Spring {
public static void main(String[] args) {
AnnotationConfigApplicationContext cont = new AnnotationConfigApplicationContext(SpringConfig.class);
Object myTestBean = cont.getBean("com.Iron.MyComponent.TestBean1");
System.out.println(myTestBean);
}
}
Spring工厂后处理器