十分钟实现自定义注解(基于Springboot后置处理方法实现自定义注解)

1,407 阅读2分钟

1.概述

自定义注解时,除了可以使用Springboot AOP的切点拦截以外,还能使用进行Springboot的钩子方法实现注解的功能。在上一篇文章中,使用了SpringBoot AOP实现了自定义注解:juejin.cn/post/704025…

2.Springboot中Bean的初始化方法

在Springboot初始化Bean的过程中,有很多Bean初始化的钩子方法如:BeanFactoryPostProcessor,ApplicationContextAware,BeanPostProcessor等,在部分钩子方法中,可以添加对自定义注解的解析。在这篇文章中,将会使用BeanPostProcessor实现 ☝️ 个普通的自定义注解。

首先,在Springboot中,BeanPostProcessor🪝 接口的作用是对Bean进行初始化操作,对Bean进行属性值的填充或者其他的一些处理,实现BeanPostProcessor接口需要实现两个方法:postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,定义该接口的类会在Bean被实例化后被调用(PS:也就是会在 BeanFactoryPostProcessor 之后被调用)。

3.使用BeanPostProcessor接口实现自定义注解的解析

  1. 首先定义 ☝️ 个注解 HunterBeanAnnoVer1,然后将这个注解用在类的属性中。
import java.lang.annotation.*;

/**
 * 自定义注解,通过 BeanPostProccessor 实现
 */
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HunterBeanAnnoVer1 {
    String param() default "null thing";
}
  1. 实现BeanPostProcessor接口,并在其中的实现 postProcessBeforeInitialization 方法
import com.Annos.HunterBeanAnnoVer1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;

@Component
public class HunterBeanFectAnnoProccessor implements BeanPostProcessor {

    private Logger logger = LoggerFactory.getLogger(HunterBeanFectAnnoProccessor.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 利用反射对类中的属性进行解析
        Field[] fields = bean.getClass().getDeclaredFields();
        for(int i = 0;i < fields.length;i += 1) {
            Field field = fields[i];
            field.setAccessible(true);
            HunterBeanAnnoVer1 ver1 = field.getAnnotation(HunterBeanAnnoVer1.class);
            if(ver1 == null) {
                continue;
            }
            String str = ver1.param();
            try {
                field.set(bean, str);
                logger.info("HunterBeanAnnoVer1赋值完成!");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return bean;
    }
}
  1. 定义一个使用注解 @HunterBeanAnnoVer1 的属性。

import com.Annos.HunterBeanAnnoVer1;
import org.springframework.stereotype.Component;

@Component
public class GunDamClass {

    @HunterBeanAnnoVer1(param = "注解解析!")
    private String name;

    public String getName() {
        return name;
    }
}
  1. 实现 ☝️ 个Controller对 GunDamClass 类进行调用。
import com.Beans.GunDamClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PlatController {

    @Autowired
    private GunDamClass gunDamClass;

    @RequestMapping("/gundamName")
    @ResponseBody
    public String getName() {
        System.out.println(gunDamClass.getName());
        return gunDamClass.getName();
    }

}
  1. 调用Controller后,就会返回自定义注解中的值。 image.png

4.总结

最近接触了很多关于自定义注解实现的代码✈️,大多基于SpringBoot实现的,因此对自定义注解进行一些研究和实践。除了依赖Spring框架实现注解外,还用使用原生java提供的接口/方法实现自定义注解的方式。比如使用Java中的AbstractProcessor实现注解解析处理,我们可以在下篇文章中继续讲解。