本文将举例说明,如果自定义一个注解Name,并通过注解给类的属性注入值
如何通过Spring配置类处理注解
- 定义注解
- 定义一个Spring配置类
- 在配置类中使用Java反射注入静态属性
定义注解
定义一个注解“Name”,Name注解可以接收一个String类型的属性,并且可以使用在类或者属性上
1 | @Target({ElementType.TYPE, ElementType.FIELD}) |
定义Sping 配置类
定义一个Spring配置类,并使用@PostConstruct注解方法实现在Spring启动过程中处理注解
1 | @Configuration |
使用Java反射注入静态属性
通过Java反射获取指定类的属性,并判断其中是否使用Name注解,有的话就获取Name注解的值,并注入到该静态属性中
tips:这里要指定会使用到Name注解的类,例子中就是Xiaohong.class
1 | @Configuration |
在属性上中使用注解
在类中的某个属性上使用注解Name,并指定值为“小红”
1 | public class Xiaohong { |
测试一下
如下例子会打印出:
hello, my name is 小红
1 | @RunWith(SpringRunner.class) |
在类上中使用注解
在类上使用注解Name,并指定值为“小白”
1 | @Name("小白") |
测试一下
如下例子会打印出:
hello, my name is 小白
1 | @RunWith(SpringRunner.class) |
为什么只能注解在作用与静态属性
通过上面的方法我们自动,Java注入属性的时候是在Spring启动过程中,并不是运行过程,所以这时候只知道类,而不知道对象。
而只有静态属性的注入是不需要指定对象的,所以静态属性可以通过这种方式来注入。
假如我们想要处理非静态属性的注入,可以封装一个注解处理方法,在运行过程中创建对象之后(例如构造方法中),调用注解处理方法,即可达到效果。
例如:
在构造方法中处理注解
定义一个方法setName(),用来处理Name注解,并以使用了Name注解的对象作为参数;在构造方法中调用这个方法。
1 | @Name("小蓝") |
测试一下
如下例子会打印出:
hello, my name is 小蓝
1 | @RunWith(SpringRunner.class) |
tips: 实际使用过程中建议抽象一个超类,使用超类的构造方法来处理注解。
总结
沿着上文的思路我们可以发现,自定义注解的重点在于 根据注解要达到的目的,考虑如何处理注解。
例如: 本文的需求是通过注解来注入一个属性,考虑到属性可以为static,所以通过Spring配置加反射的方式; 如果属性不能为static,则可以通过构造方法来实现。
在实际开发中,处理注解还有其他多种方式,各有优缺点。
例如:
在Bean的后置处理器中处理注解
通过实现Bean的后置处理器方法,配合Java反射。
这种注解可以使用在类、方法、属性上。
局限性是这种注解只能在Spring Bean中使用。
参考SpringBoot之自定义注解(基于BeanPostProcessor接口实现)通过Spring AOP处理
原理是通过注解来定义切点。
优点是编写简单。
但这种注解也只能使用在Spring Bean中,且只能作用于方法上
参考SpringBoot之自定义注解(基于AOP实现)通过AspectJ切面处理
通过SspectJ切面编程实现,类似SPring AOP切面。而已没有只能作用在方法上的局限通过Spring配置类处理
通过配置类实现在Spring启动过程中处理注解,配置Java反射机制来注入静态变量。
局限性是只能注入静态属性。
这也是本文所使用的方法。