0

0

SpringBoot怎么通过自定义注解实现配置类的自动注入

WBOY

WBOY

发布时间:2023-05-14 22:34:12

|

2130人浏览过

|

来源于亿速云

转载

前言

springboot中通过@configurationproperties@value注解就可以获取配置文件中的属性定义并绑定到java bean或属性上,这也是我们平常使用最多的一种方式。但是小胖在开发过程中就遇到一个问题:在做mq的开发中,配置文件中会配置多个生产者分别提供不同的业务能力,如果通过@configurationproperties注解来实现的话,这就意味着需要创建多个属性一样的配置类,虽然说可以实现功能,但是很明显,这不是一个很好的设计。场景如下所示:

producer1:
    password: xxx
    app: xxx
    address: url1
    enabled: false
    
producer2:
    password: xxx
    app: xxx
    address: url1
    enabled: false

实现思路

在我们日常的开发工作中,经常可以见到的是通过自定义注解+拦截器+反射从而实现对权限的校验或者对实体类字段值格式进行校验。那么,我们是不是也可以参考这个思路达到我们的目的呢?答案是肯定的,其实如果对Mabatis等组件比较熟悉的话,就可以看到这样的设计。我们话不多少,开搞~

开搞

以下内容,为了方便,我们将配置相关内容改为人员(people)

自定义配置类读取配置

首先,有一点是不会改变的,我们需要自定义一个配置类,用于读取配置文件中的配置。这里,我们需要改变一下我们配置文件信息里。将所有的配置信息放到一个类里。

my:
  peoples:
    people1:
      userName: 张三
      userSex: 男
    people2:
      userName: 李四
      userSex: 女

然后,定义一个配置类用来接收,这里通过@ConfigurationProperties注解实现对配置的注入。要注意,因为我们在peoples下面有很多的people,因此,属性应给定义的是一个MAP的类型。

@Component
@ConfigurationProperties(prefix = "my",ignoreUnknownFields = false)
public class PeopleConfigs {

    private MapzuojiankuohaophpcnString, PeopleEntityyoujiankuohaophpcn peoples;

    public MapzuojiankuohaophpcnString, PeopleEntityyoujiankuohaophpcn getPeoples() {
        return peoples;
    }

    public void setPeoples(MapzuojiankuohaophpcnString, PeopleEntityyoujiankuohaophpcn peoples) {
        this.peoples = peoples;
    }

    @Override
    public String toString() {
        return "PeopleConfigs{" +
                "peoples=" + peoples +
                '}';
    }
}

public class PeopleEntity {

    private String userName;
    private String userSex;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    @Override
    public String toString() {
        return "PeopleEntity{" +
                "userName='" + userName + ''' +
                ", userSex='" + userSex + ''' +
                '}';
    }
}

这样,Springboot就会自动加载我们这个配置类。但是,这个的整个PeopleConfigs是一个Bean,并不能达到我们本文的目的,因此我们进行后续的步骤。

自定义注解

我们声明一个运行时的注解,在属性上进行使用。这里定义name用来标记需要注入的是哪个人。

Endel.io
Endel.io

Endel是一款可以创造个性化舒缓声音的应用程序,可帮助您集中注意力、放松身心和入睡。

下载
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface People {
    String name() default "";
}

创建子配置Bean

首先,定义一个autoConfig的配置类,该类通过@EnableConfigurationProperties注解,指定PeopleConfig Bean在本类之前进行装载。通过@Bean方法注解进行bean声明,此处调用的是单个people配置类的bean生成的方法。

@Configuration
@EnableConfigurationProperties({PeopleConfigs.class})
public class PeopleAutoConfig {

    @Autowired
    PeopleConfigs peopleConfigs;

    @Bean
    public PeopleRegister peopleRegister(){
        return new PeopleRegister(peopleConfigs);
    }
}

通过反射进行people bean的注入

这里不得不提到BeanPostProcessor类,该类为我们提供了springBoot在bean初始化前后方便我们进行其他自定义操作的一些接口。我们这里通过实现postProcessBeforeInitialization方法,在bean装载之前,通过反射判断对应bean上是否有我们自定义的people注解。如果有,则进行注入操作。详细代码如下:

public class PeopleRegister implements BeanPostProcessor, ApplicationContextAware {

    private final PeopleConfigs peopleConfigs;

    private GenericApplicationContext applicationContext;

    PeopleRegister(PeopleConfigs peopleConfigs){
        this.peopleConfigs = peopleConfigs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Classzuojiankuohaophpcn?youjiankuohaophpcn beanClass = AopUtils.getTargetClass(bean);
        Field[] fields = beanClass.getDeclaredFields();
        Field[] var5 = fields;
        int var6 = fields.length;

        for(int var7 = 0;var7zuojiankuohaophpcnvar6;var7++){
            Field field = var5[var7];
            People annotation = field.getAnnotation(People.class);
            if (annotation!=null){
                PeopleEntity entity = this.peopleConfigs.getPeoples().get(annotation.name());
                if (!this.applicationContext.containsBean(annotation.name())){
                    ConfigurableListableBeanFactory beanFactory = this.applicationContext.getBeanFactory();
                    Object wrapperBean = beanFactory.initializeBean(entity, annotation.name());
                    beanFactory.registerSingleton(annotation.name(), Objects.requireNonNull(wrapperBean));
                }

                try{
                    field.setAccessible(true);
                    field.set(bean, this.applicationContext.getBean(annotation.name(), PeopleEntity.class));
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (GenericApplicationContext)applicationContext;
    }
}

使用

前面工作进行完成后,接下来就是我们的使用环节,这里,我们仅需要通过@People(name = "人")指定即可:

@Controller
public class BaseController {

    @Autowired
    PeopleConfigs peopleConfigs;
    @People(name = "people1")
    PeopleEntity people1;
    @People(name = "people2")
    PeopleEntity people2;

    @ResponseBody
    @GetMapping("/test")
    public String test() {
        return peopleConfigs.toString()+people1.toString()+people2.toString();
    }
}

效果

SpringBoot怎么通过自定义注解实现配置类的自动注入

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

804

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

723

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

727

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

395

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

445

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

428

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16861

2023.08.03

vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

28

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Redis6入门到精通超详细教程
Redis6入门到精通超详细教程

共47课时 | 5.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号