Java注解读这一篇就够了

前言:
我写了很多上层框架的知识,自以为会有很多人会很感兴趣,但发现其实看的人
很少。于是我自己反思了一下为什么会这样,因为框架这种东西真的比较好学,
随便买本书,或者看个什么什么视频,就比我写的博文好太多了,我思前想后很
久,还是打算从那些容易忽略的细小知识出发,重新创建个javase模块,写点有
质量的东西出来。

相信很多买过java基础书籍的同学都知道—java对注解这一块的描述普遍少的可怜,网上也找不到什么好的视频,于是我打算从jdk自带的注解来模仿别人是怎么写的。我会在讲述过程中加上自己的学习时的心得。好了,话不多说了,直奔主题吧。

直接上图说明问题:下图是jdk内置注解 @SuppressWarnings 的源码 , 我们可以很清晰的发现,自定义的注解需要如下的三个东西(元注解、@interface、方法形式的属性

在这里插入图片描述
我来说明一下上面的三个关键因素!

先从@interface说起吧。看下图我们能很直观的看出Annotation(注解) 是和Class(类)、Interface(接口)平级的东西,而写上@interface 就可以表明你写的这个文件是个注解类。

在这里插入图片描述

元注解:修饰注解的注解,有下面四个:
注解功能
@Target限制注解,限制注解使用的地方(属性、方法、类);如果一个注解没有@Target描述,则该 注解可以修饰任何类型的元素;如果有@Target修饰,则该注解就只能用于被@Target修饰的地方,属性的填写参考 ElementType 枚举类
@Retention限制注解的生命周期,属性的填写参考 RetentionPolicy 枚举类(里面只有三个,SOURCE:该注解无效、CLASS:程序在编译时会使用该注解,在运行是不会使用、RUNTIME:程序在编译以及运行时,都会使用注解)
@Document默认情况下,javadoc 不包含注解的解释;如果现在javadoc文档中也包含对注解的说明,则需要使用@Document标注
@Inherited默认情况下子类不会继承父类的注解。除非父类的注解里面写有该元注解,则子类也会享有父类的注解(里面写有该元注解)
方法形式的属性:想要给注解定义一些属性,则必须将需要定义的属性写成抽象方法的形式。

下面我将展示一下通过自定义注解,来完成加法运算

  • 1.编写注解类:
package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(value = {ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface luzelong {
    int x() default 0;//给x属性的默认值设为0
    int y() default 0;//给y属性的默认值设为0
}
  • 2.通过反射来获取注解的属性并完成加法操作:
package annotation;

import java.lang.annotation.Annotation;
import static java.lang.Class.forName;

public class Test {
    @luzelong(x = 12, y = 25)
    public static int longlong() {
        luzelong lzl = null;
        try {
            lzl = forName("annotation.Test").getMethod("longlong").getAnnotation(luzelong.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if(lzl != null)
            return lzl.x() + lzl.y();
        else
            return -1;
    }

    public static void main(String[] args) {
        System.out.println(longlong());
    }
}

运行结果如下:
在这里插入图片描述

配合注解的常用反射方法

第三个方法存在部分标有注解的方法未能执行的问题,大佬能解决的话评论区留言!

	/**
     * 获取某个包中的所有类
     * @param packageName
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private List<Class> getAllClazz(String packageName) throws IOException, ClassNotFoundException {

        List<Class> ret = new ArrayList<>();

        PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
        Resource[] resources = (Resource[]) pathMatchingResourcePatternResolver.getResources("classpath*:"+packageName+"/**/*.class");
        ClassLoader loader = ClassLoader.getSystemClassLoader();

        for (Resource resource : resources) {
            MetadataReader reader = cachingMetadataReaderFactory.getMetadataReader((org.springframework.core.io.Resource) resource);
            String className = reader.getClassMetadata().getClassName();
            Class aClass = loader.loadClass(className);
            ret.add(aClass);
        }
        return ret;
    }
    /**
     * 获取某个包中的所有  k-v = class-method
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public HashMap<Class,Method> getAllFMethod(String packageName) throws IOException, ClassNotFoundException {
        HashMap<Class,Method> mothods = new HashMap<>();
        List<Class> allClazz = getAllClazz(packageName);
        for (Class clazz : allClazz) {
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                mothods.put(clazz,declaredMethod);
            }
        }
        return mothods;
    }


    /**
     * 执行某个包中 带有annotation注解的全部方法(该方法存在问题,大佬能解决的话评论区留言)
     * @param packageName
     * @param annotation
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public void exeMethod_Obtain_Some_Annotation(String packageName,Class annotation) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
        HashMap<Class, Method> allFMethods = getAllFMethod(packageName);
        for (Map.Entry<Class,Method> funcMethod : allFMethods.entrySet()){
            funcMethod.getValue().setAccessible(true);
            if (funcMethod.getValue().isAnnotationPresent(annotation)){
                System.out.println(funcMethod);
                funcMethod.getValue().invoke(funcMethod.getKey().newInstance());
            }
        }

    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

键盘歌唱家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值