您好,欢迎访问一九零五行业门户网

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

前言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 map<string, peopleentity> peoples; public map<string, peopleentity> getpeoples() { return peoples; } public void setpeoples(map<string, peopleentity> 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用来标记需要注入的是哪个人。
@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 { class<?> beanclass = aoputils.gettargetclass(bean); field[] fields = beanclass.getdeclaredfields(); field[] var5 = fields; int var6 = fields.length; for(int var7 = 0;var7<var6;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 = "人")指定即可:
@controllerpublic 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怎么通过自定义注解实现配置类的自动注入的详细内容。
其它类似信息

推荐信息