Java自定义注解(详细版)
为什么要自定义注解
当然是为了装逼
为了能够在编写代码的时候,使得自己注入的代码更加直观,也显得耦合度更低。
正式步骤
先介绍通用的部分
第一步:声明自己要使用的注解
以此举例:
package com.pbinterface.demo;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
String value() default "111";
}
这里需要解释的有个部分:
- @Target注解:用于声明本注解是用于注解在什么地方上的,这里是用于注解在字段上面的;
- @Retention(RententionPolicy.RUNTIME) 这个注解则是用于注明本注解可以用反射获取;
- String value() 这一部分则是用于声明这个注解有什么属性,default用于声明默认值;
Target中可选的不仅有字段,还有方法、类、构造器等等,这里就不全部展开了。
然后就是特有的部分。
毕竟现在只是声明了有这么个注解,这个注解暂时还没有任何功能。
注解字段
依旧按照上述的例子,我们希望被这个注解注解的字段,自动注入我们预想的值,可以这么写:
@Component
public class AnnotationHandler implements BeanPostProcessor {
// 使用反射获取字段并注入属性
public Object postProcessAfterInitialization(Object bean, String BeanName){
Class<?> clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if(field.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class);
field.setAccessible(true);
try {
field.set(bean, myAnnotation.value());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
return bean;
}
}
这里声明了一个处理器,实现了BeanPostProcessor接口,使得这个类可以在Bean初始化的时候,进行属性注入。
注解方法
通过切面实现对于方法的注解。
//这是注解方法的注解样例
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
String value() default "";
}
//这是实现功能的类
@Aspect
@Component
public class AnnotationHandler2 {
@Pointcut("@annotation(com.pbinterface.demo.MyAnnotation2)")
public void pointcut() {}
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
Object obj = joinPoint.getTarget(); // 获取到切点的实例,然后想干什么都可以了
}
}
注解方法中参数
这个当然也可以使用切面的方式来达成,不过这里给出另一种方法。
// 这是被注解的类,需要注意的是,必须是Controller层的网络路径方法
@Controller
public class TestClass {
@GetMapping("/test")
public void run(@MyAnnotation3 String haha){
System.out.println(haha);
}
}
// 注解
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation3 {
String value() default "AutoTest";
}
// 处理器,实现了这个接口
@Component
public class AnnotationHandler3 implements HandlerMethodArgumentResolver {
// 判断参数是否符合条件
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(MyAnnotation3.class);
}
// 解析参数,返回值就是修改后的参数
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return Objects.requireNonNull(parameter.getParameterAnnotation(MyAnnotation3.class)).value();
}
}
// 配置类,若不配置,则不生效
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final AnnotationHandler3 annotationHandler3;
public WebConfig(AnnotationHandler3 annotationHandler3) {
this.annotationHandler3 = annotationHandler3;
}
// 添加解析器
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(annotationHandler3);
}
}

浙公网安备 33010602011771号