java:自定义注解,并使用【ImportBeanDefinitionRegistrar】动态加载

# 项目代码资源:

可能还在审核中,请等等。。。
https://download.csdn.net/download/chenhz2284/89432848

# 主项目

【pom.xml】

<groupId>com.chz</groupId>
<artifactId>chzopen_study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
    <module>myBeanMain</module>
    <module>myBeanBranch2</module>
</modules>

子模块【myBeanBranch2】

【pom.xml】

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.15.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.15.RELEASE</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>1.3.5</version>
</dependency>

【MyRegistrarAnnotation.java】

package com.chz.myBeanRegistrar.annotation;

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
public @interface MyRegistrarAnnotation {
}

【MyImportBeanDefinitionRegistrar.java】

package com.chz.myBeanRegistrar.beanRegistrar;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry,
                                        BeanNameGenerator importBeanNameGenerator)
    {
        try {
            // 这里开始扫描包里面的类
            MyRegistrarScanner scanner = new MyRegistrarScanner(EnableBranchRegistrar.class.getPackageName());
            List<Class<?>> targetClassList = scanner.scan();
            for( Class<?> klass : targetClassList ){
                // 扫到类之后注册成一个bean
                GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
                beanDefinition.setBeanClass(klass);
                registry.registerBeanDefinition(klass.getName(), beanDefinition);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args)
    {
        MyRegistrarAnnotation annotation = BranchRegistrarController.class.getAnnotation(MyRegistrarAnnotation.class);
        System.out.println(annotation);
    }
}

【BranchRegistrarController.java】

package com.chz.myBeanRegistrar.controller;

@Slf4j
@MyRegistrarAnnotation    // 这里添加了我们自己的注解
@ResponseBody
@RequestMapping("/branch/registrar")
public class BranchRegistrarController {

    public BranchRegistrarController()
    {
        log.info("chz >>> BranchRegistrarController.<init>()");
    }

    @GetMapping("/test1")
    public String test1() {
        return "test1: BranchRegistrarController";
    }
}

【ClassScanner.java】

package com.chz.myBeanRegistrar.scan;

@Slf4j
public class ClassScanner {

    private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    private String basePackage;
    private ClassLoader classLoader;
    private Matcher matcher;

    public ClassScanner(String basePackage, Matcher matcher)
    {
        this(basePackage, matcher, null);
    }

    public ClassScanner(String basePackage, Matcher matcher, ClassLoader classLoader)
    {
        this.basePackage = basePackage;
        this.classLoader = classLoader!=null ? classLoader : this.getClass().getClassLoader();
        this.matcher = matcher;
    }

    public List<Class<?>> scan() throws IOException {
        List<Class<?>> candidates = new ArrayList<>();
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + convertPath(basePackage) + '/' + DEFAULT_RESOURCE_PATTERN;
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        MetadataReaderFactory readerFactory = new SimpleMetadataReaderFactory(resourceLoader);
        Resource[] resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources(packageSearchPath);
        for (Resource resource : resources) {
            Class<?> clazz = transformToClass(readerFactory.getMetadataReader(resource).getClassMetadata().getClassName());
            if( matcher.match(clazz) ) {
                candidates.add(clazz);
            }
        }
        return candidates;
    }

    private Class<?> transformToClass(String className) {
        Class<?> clazz = null;
        try {
            clazz = ClassUtils.forName(className, classLoader);
        } catch (ClassNotFoundException e) {
            log.info("未找到指定类", className, e);
        } catch (NoClassDefFoundError e) {
            log.info("未找到指定类", className, e);
            throw e;
        }
        return clazz;
    }

    private String convertPath(String path) {
        return StringUtils.replace(path, ".", "/");
    }

    public interface Matcher
    {
        boolean match(Class<?> clazz);
    }
}

【MyRegistrarScanner.java】

package com.chz.myBeanRegistrar.scan;

public class MyRegistrarScanner {

    private ClassScanner classScanner;

    public MyRegistrarScanner(String basePackage){
        classScanner = new ClassScanner(basePackage, new MoMatcher());
    }

    public MyRegistrarScanner(String basePackage, ClassLoader classLoader){
        classScanner = new ClassScanner(basePackage, new MoMatcher(), classLoader);
    }

    public List<Class<?>> scan() throws IOException {
        return (List<Class<?>>)(Object)classScanner.scan();
    }

    private static class MoMatcher implements ClassScanner.Matcher
    {
        @Override
        public boolean match(Class<?> clazz) {
            // 注意这些:要求class必须有【MyRegistrarAnnotation】注解
            return isAbstract(clazz)==false && clazz.getAnnotation(MyRegistrarAnnotation.class)!=null;
        }
    }

    public static boolean isAbstract(Class<?> clazz)
    {
        return Modifier.isAbstract(clazz.getModifiers());
    }
}

【EnableBranchRegistrar.java】

package com.chz.myBeanRegistrar;

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import({
        MyImportBeanDefinitionRegistrar.class,                 // 这里使用了 ImportBeanDefinitionRegistrar
})
public @interface EnableBranchRegistrar {
}

# 子模块:【myBeanMain】

【pom.xml】

<dependency>
    <groupId>com.chz</groupId>
    <artifactId>myBeanBranch2</artifactId>
    <version>${project.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.12.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>2.3.12.RELEASE</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>

【application.properties】

server.port=8080
spring.application.name=myBeanMain

management.server.port=7001
management.endpoints.web.exposure.include=*

【MainBean.java】

package com.chz.myBeanMain.bean;

@Slf4j
@Getter
@Setter
@Component
public class MainBean {

    @Autowired(required = false)
    private NotAnnotatedBean notAnnotatedBean;

    public MainBean()
    {
        log.info("chz >>> MainBean.<init>()");
    }

    @PostConstruct
    public void init()
    {
        log.info("chz >>> MainBean.init()");
    }
}

【NotAnnotatedBean.java】

package com.chz.myBeanMain.bean;

// 被【@Import】指过来的bean不需要添加【@Component】
@Slf4j
@Getter
@Setter
public class NotAnnotatedBean {

    private String name = "I am " + this.getClass().getSimpleName();

    public NotAnnotatedBean()
    {
        log.info("chz >>> NotAnnotatedBean.<init>()");
    }
}

【MainConfiguration.java】

package com.chz.myBeanMain.config;

@Slf4j
@Configuration
public class MainConfiguration {

    public MainConfiguration()
    {
        log.info("chz >>> MainConfiguration.<init>()");
    }
}

【MainController.java】

package com.chz.myBeanMain.controller;

@Slf4j
@RestController
@RequestMapping("/main")
public class MainController {

    @Autowired(required = false)
    private MainBean mainBean;

    @GetMapping("/notAnnotatedBean")
    public String notAnnotatedBean() {
        return "notAnnotatedBean: " + mainBean.getNotAnnotatedBean().getName();
    }
}

【MyBeanMainTest.java】

package com.chz.myBeanMain;

@Import(NotAnnotatedBean.class)         // 这里使用了@Import
@EnableBranchRegistrar                  // 这里使用了@ImportBeanDefinitionRegistrar
@SpringBootApplication
public class MyBeanMainTest {

    public static void main(String[] args) {
        SpringApplication.run(MyBeanMainTest.class, args);
    }
}

# 运行

运行【MyBeanMainTest】,可以看到【BranchRegistrarController】确实被注册进来了
在这里插入图片描述
访问【http://localhost:8080/branch/registrar/test1】,正常显示
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/710832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式操作系统_4.任务管理

1.任务的概念 任务管理是嵌入式操作系统最基本功能之一&#xff0c;这里的任务&#xff08;task&#xff09;是指嵌入式操作系统调度的最小单位&#xff0c;类似于一般操作系统进程或线程的概念。任务是运行中的一个程序&#xff0c;一个程序加载到内存后就变成任务&#xff1…

InnoDB和MyISAM有什么区别?

InnoDB和MyISAM是MySQL中比较常用的两个执行引擎&#xff0c;MySQL在 5.5 之前版本默认存储引擎是 MyISAM,5.5 之后版本默认存储引擎是 InnoDB&#xff0c;MYISAM适合查询以及插入为主的应用&#xff0c;InnoDB适合频繁修改以及涉及到安全性较高的应用。 如果应用需要高度的数…

如果给电商系统颜值搞排名,我觉得淘宝千牛系统是天花板了。

淘宝的商家操作界面-千牛系统经过多年的迭代&#xff0c;无论从颜值上、功能上还是用户体验上都是行业天花板的存在&#xff0c;我截图软件上的一些图给大家分享下。

AirPlay技术规范及认证资讯

AirPlay是Apple开发的一种无线技术&#xff0c;允许用户将音频、视频或图片从iOS设备、Mac电脑或其他支持AirPlay的设备无线传输到支持AirPlay的接收器设备上&#xff0c;例如智能电视或音响系统。这项技术基于Wi-Fi网络&#xff0c;提供了一种便捷的方式来共享媒体内容。AirPl…

模型 POA行动

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。让目标凝聚伙伴&#xff0c;伙伴共创方法&#xff0c;加速实现愿景&#xff0c;可谓是行动力的“飞轮效应”。 1 POA行动模型的应用 1.1 POA模型在非营利组织&#xff08;NGO&#x…

算法day31

第一题 542. 01 矩阵 本题本来求解的是每一个1到0的最短距离并返回到矩阵之中&#xff1b; 我们采用正难则反的思路&#xff0c;将其化解为每一个0到每一个1的最短距离&#xff0c;并通过矩阵来返回&#xff1b; 解法&#xff1a;多源bfs正难则反 步骤一&#xff1a; 定义一个…

PDF标准详解(三)—— PDF坐标系统和坐标变换

之前我们了解了PDF文档的基本结构&#xff0c;并且展示了一个简单的hello world。这个hello world 虽然只在页面中显示一个hello world 文字&#xff0c;但是包含的内容却是不少。这次我们仍然以它为切入点&#xff0c;来了解PDF的坐标系统以及坐标变换的相关知识 图形学中二维…

利用Cesium和JS实现地点点聚合功能

引言 在实现基于地图的业务场景时&#xff0c;当地图上需要展示过多的标记点时&#xff0c;大量的分散点会使地图上显得杂乱无章&#xff0c;导致标记点对地图上的其他重要信息造成遮挡和混淆&#xff0c;降低地图整体的可读性。 标记点的聚合就很好的解决了这些痛点的同时&a…

线性规划问题——单纯形算法

第一步&#xff1a;化“约束标准型” 在每个等式约束中至少有一个变量的系数为正&#xff0c;且这个变量只在该约束中出现。在每个约束方程中选择一个这样的变量称为基本变量。 剩下变量称为非基本变量。 一个简单的栗子 上图是一个约束标准型线性规划的例子。 等式1&#x…

几款让你怦然心动的神奇工具——搜嗖工具箱

alteredqualia AlteredQualia 脑洞爆炸器网站&#xff0c;不得不说这是一个神奇的网站&#xff0c;在这个网站上你可以实现不可思议的各种操作&#xff0c;让我们对网站有了新的认知&#xff0c;因为它告诉你不是所有有趣的网站都那么花哨&#xff0c;有些网站看着外形平淡无奇…

AI实践与学习5-AI解题场景RAG应用预研demo

背景 AI解题场景现状&#xff0c;教研测评文档&#xff1a;xxx 解题正确率仍需进一步提高&#xff0c;提示词优化方案基本无力o目前配置的易错题CoT示例支持的长度有限&#xff0c;后续题量大的时候配置具有局限性。某些英语翻译题型BAD CASE反映大模型的输出格式不太符合要求…

设置sqlserver management的字体大小

在用sqlserver management的时候&#xff0c;总感觉怪怪的&#xff0c;然后发现是字体太小的原因。 1&#xff09;设置一下字体&#xff0c;工具--选项&#xff1a; 2&#xff09;环境--字体和颜色--显示其设置&#xff08;环境&#xff09; 3&#xff09;选择微软雅黑&#xf…

在Kubernetes中部署Elasticsearch高可用集群详细教程

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

btrace:binder_transaction+eBPF+Golang实现通用的Android APP动态行为追踪工具

一、简介&#xff1a; 在进行Android恶意APP检测时&#xff0c;需要进行自动化的行为分析&#xff0c;一般至少包括行为采集和行为分析两个模块。其中&#xff0c;行为分析有基于规则、基于机器学习、基于深度学习甚至基于大模型的方案&#xff0c;各有各的优缺点&#xff0c;不…

Photoshop中颜色与色调的调整

Photoshop中颜色与色调的调整 Photoshop中的颜色模式RGB模式灰度模式位图模式索引模式CMYK模式Lab模式 Photoshop中的颜色/色调调整命令颜色/色调调整命令的分类亮度/对比度调整命令色阶命令曲线命令曝光度命令自然饱和度命令色相/饱和度命令色彩平衡命令照片滤镜调整命令通道混…

一篇文章教你学会公众号IP写作(新手小白必备)

最近在带大家玩公众号 IP 写作&#xff0c;很多新手小白常问的问题&#xff0c; 1 什么是IP写作&#xff1f; “IP写作&#xff0c;简单来说&#xff0c;就是通过在公众号上持续写出有价值的文章&#xff0c;来建立个人影响力。 让读者了解你、信任你、找你付费。实现高价值、强…

MySQL之优化服务器设置(二)

优化服务器设置 InnoDB事务日志(包含:Redo log 重做日志和Undo log回滚日志) 了解清楚"把日志缓冲写到日中文件"和"把日志刷新到持久化存储"之间的不同是很重要的。在大部分操作系统中&#xff0c;把缓冲写到日志只是简单地把数据从InnoDB的内存缓冲转移…

MySQL中的正排/倒排索引和DoubleWriteBuffer

正排/倒排索引 正排索引 文档1&#xff1a;词条A&#xff0c;词条B&#xff0c;词条C 文档2&#xff1a;词条A&#xff0c;词条D 文档3&#xff1a;词条B&#xff0c;词条C&#xff0c;词条E正排表是以文档的ID为关键字&#xff0c;表中记录文档中的每个字的位置信息&#xff…

人事信息管理系统(Java+MySQL)

一、项目背景 在现代企业中&#xff0c;管理大量员工的工作信息、薪资、请假、离职等事务是一项非常繁琐和复杂的任务。传统的手工管理方式不仅效率低下&#xff0c;而且容易出错。为了提高人事管理的效率&#xff0c;减少人工操作带来的错误&#xff0c;企业迫切需要一个高效…

怎样收集企业名单?

收集企业名单的方法按照不同维度有不同的方式&#xff0c; 通过人工一个个收集&#xff0c;通过技术手段收集&#xff0c;通过第三方进行购买。 按照来源渠道&#xff0c;可以分为官方和非官方网站&#xff0c;官方的有公示系统&#xff0c;年报等。此外一些相对于官方的平台…