当前位置: 首页 > news >正文

@ComponentScan组件扫描原理(二)

       接着之前的处理,在拿到注解元信息之后,我们可以进一步处理,并生成Bean。下面是完整的组件扫描解析流程。

public static void main(String[] args) throws IOException {GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config", Config.class);/* context.registerBean(ConfigurationClassPostProcessor.class);//@ComponentScan @Bean @Import注解 @ImportResource注解context.registerBean(MapperScannerConfigurer.class,beanDefinition -> {beanDefinition.getPropertyValues().add("basePackage","com.example.demo2.b03.mapper");});*/ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);if (componentScan!= null) {for (String p : componentScan.basePackages()){System.out.println(p);String path = "classpath*:"+p.replace(".","/")+"/**/*.class";System.out.println(path);CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();Resource[] resources = context.getResources(path);for (Resource resource : resources){//System.out.println(resource);MetadataReader reader = factory.getMetadataReader(resource);//System.out.println("类名:"+reader.getClassMetadata().getClassName());AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();/* System.out.println("是否加了@Component注解:"+reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));System.out.println("是否加了@Component派生注解:"+reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));*/if(annotationMetadata.hasAnnotation(Component.class.getName())|| annotationMetadata.hasMetaAnnotation(Component.class.getName())){AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();DefaultListableBeanFactory defaultListableBeanFactory = context.getDefaultListableBeanFactory();String name = generator.generateBeanName(bd, defaultListableBeanFactory);defaultListableBeanFactory.registerBeanDefinition(name,bd);}}}}//初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){System.out.println(name);}//销毁容器context.close();}

结果输出如下:

         bean2和bean3被成功扫描并注入到Spring容器中了。进一步提取主类的处理方法,抽象成一个BeanFactoryPostProcessor。

package com.example.demo2.b03;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
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.DefaultListableBeanFactory;
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;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/7 21:22*/
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {try {ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);if (componentScan!= null) {for (String p : componentScan.basePackages()){System.out.println(p);String path = "classpath*:"+p.replace(".","/")+"/**/*.class";System.out.println(path);CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);for (Resource resource : resources){//System.out.println(resource);MetadataReader reader = factory.getMetadataReader(resource);//System.out.println("类名:"+reader.getClassMetadata().getClassName());AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();/* System.out.println("是否加了@Component注解:"+reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));System.out.println("是否加了@Component派生注解:"+reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));*/if(annotationMetadata.hasAnnotation(Component.class.getName())|| annotationMetadata.hasMetaAnnotation(Component.class.getName())){AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();//DefaultListableBeanFactory defaultListableBeanFactory = context.getDefaultListableBeanFactory();if(configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory){String name = generator.generateBeanName(bd, beanFactory);beanFactory.registerBeanDefinition(name,bd);}}}}}} catch (IOException e) {e.printStackTrace();}}
}

       自定义的ComponentScanPostProcessor类实现BeanFactoryPostProcessor接口并重写方法,里面的逻辑就是我们在主方法里面写的处理逻辑。

 public static void main(String[] args) throws IOException {GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config", Config.class);/* context.registerBean(ConfigurationClassPostProcessor.class);//@ComponentScan @Bean @Import注解 @ImportResource注解context.registerBean(MapperScannerConfigurer.class,beanDefinition -> {beanDefinition.getPropertyValues().add("basePackage","com.example.demo2.b03.mapper");});*/context.registerBean(ComponentScanPostProcessor.class);//初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){System.out.println(name);}//销毁容器context.close();}

           只要把我们自定义的工厂后处理器注入到Spring容器中,便可以实现组件扫描。

http://www.dtcms.com/a/455441.html

相关文章:

  • linux网络服务+linux数据库4
  • 做网站的代码难吗wordpress弹窗视频播放插件
  • 网站网址更新了怎么查镇江网站制作服务
  • 智能硬件开发流程网站优化要怎么做
  • 谁做视频网站上海网站备案中心
  • 打工人日报#20251007
  • 如何做律所网站做义工旅行有哪些网站
  • 贵阳网站建设宏思锐达银川市住房和城乡建设局网站公告
  • 连云港市建设局网站安全员考试广州网站建设支付
  • 网站粘度计算公式微信小程序制作网站
  • 有哪些做短租的网站好龙岗区住房和建设局网站打不开
  • 宝塔面板建设网站安徽人
  • 宁波制作网站企业二级域名做外贸网站好吗
  • 外卖网站的建设与推广织梦和wordpress哪个seo好
  • 专业做足球体彩网站网站备案应该怎么做
  • 什么网站可以做时间加减微信 公众号导入wordpress
  • 内江做网站哪里便宜美容院顾客管理系统软件
  • 培训网站官网企业账号登录入口
  • jq效果较多的网站世界工厂网app
  • php 手机网站乐陵seo公司
  • 上海网站制作机构西安复工无需核酸检测
  • 单页淘宝客网站2014年行吗一二三四视频社区5在线高清
  • 网站主页的要素郑州专业公司网站制作公司
  • 网站开发的平台企业网页设计模板图片
  • 多个网站优化怎么做恩施网站建设公司
  • 分类信息网站织梦模板用windows搭建手机网站
  • 安徽网站建设推广个人能接广告联盟吗
  • 汽车最专业的网站建设哪有网站给光头强做面
  • 思明区建设局官网站百度网址大全网址导航
  • 制作logo的网站静态网页制作总结