Java注解原理

(一):java元注解

java的最基本的几个注解主要有一下几个

@Target:该注解主要是作用在方法,属性,类等上
@Retention:主要有三个参数

  1.         SOURCE:当前注解编译器可见,但是不会写入到class文件
  2.         CLASS:类加载阶段会丢弃,但是会写入到class文件
  3.         RUNTIME:永久保存下来

@Documented:注解是否应当被包含在 JavaDoc 文档中,通常不用,作用不是很大
@Inherited:是否允许子类继承该注解

(二):注解原理

java当中所有的注解都是实现了Annotation这个接口,如下图所示,

(三):注解解析

一个注解解析通常有两种方式:

编译期间直接进行扫描:根据注解的名字,来判断才程序应该做什么事情,比方说spring的注解component注解的源码如下,

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	String value() default "";

}

spring是通过注解的名称来判断,spring应该对这个对象做什么事情,(实际上,是spring底层源码,通过识别注解的名字来判断的)

通过运行期间来进行反射 :

一个注解,实际上也是一个对象,所以的话,我们也可以通过java的反射机制来获取注解里面的相关内容,不多说,代码如下,

//运行在字段上的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnTargetField {

    String value() default "我是定义在字段上的注解";
}

//运行在方法上的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnTargetMethod {
    String value() default "我是定义在方法上的注解";
}

//运行在参数上的注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnTargetParameter {
    String value() default "我是定义在一个参数上的注解";
}

//运行在类上的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnTargetType {
    String value() default "我是定义在类上的注解";
}

//测试类
@MyAnTargetType
public class AnnotationTest {

    @MyAnTargetField
    private String field="我是字段";

    @MyAnTargetMethod
    public void test(@MyAnTargetParameter String args)
    {
        System.out.println("参数值sdfsdf"+args);
    }
    public static void main(String[] args) {
        // 获取类上的注解MyAnTargetType
        MyAnTargetType t = AnnotationTest.class.getAnnotation(MyAnTargetType.class);
        System.out.println("类上的注解值 === "+t.value());
        MyAnTargetMethod tm = null;
        try {
            // 根据反射获取AnnotationTest类上的test方法
            Method method = AnnotationTest.class.getDeclaredMethod("test",String.class);
            // 获取方法上的注解MyAnTargetMethod
            tm = method.getAnnotation(MyAnTargetMethod.class);
            System.out.println("方法上的注解值 === "+tm.value());
            // 获取方法上的所有参数注解  循环所有注解找到MyAnTargetParameter注解
            Annotation[][] annotations = method.getParameterAnnotations();
            for(Annotation[] tt : annotations){
                for(Annotation t1:tt){
                    if(t1 instanceof MyAnTargetParameter){
                        System.out.println("参数上的注解值 === "+((MyAnTargetParameter) t1).value());
                    }
                }
            }
            method.invoke(new AnnotationTest(), "改变默认参数");
            // 获取AnnotationTest类上字段field的注解MyAnTargetField
            MyAnTargetField fieldAn = AnnotationTest.class.getDeclaredField("field").getAnnotation(MyAnTargetField.class);
            System.out.println("字段上的注解值 === "+fieldAn.value());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果如下所示

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java注解(Annotation)是一种元数据,用于在程序中提供额外的信息但并不直接参与程序的运行。它们被用来标记代码元素,如类、方法、变量等,以便工具和构建系统能够读取这些信息并执行特定的行为。Java注解不改变源代码的实际功能,而是提供一种声明式的方式来传递上下文或配置。 注解的工作原理主要包括以下几个步骤: 1. **编写注解**:程序员在源代码中定义注解,如`@Override`、`@Deprecated`等,这些是Java标准库提供的预定义注解。 2. **编译期间处理**:当源代码经过Java编译器(javac)编译时,注解会被保留下来,但不会影响字节码。编译器会在注解的位置生成对应的字节码,包含注解的数据。 3. **解析注解**:使用诸如AspectJ、IntelliJ IDEA这样的工具或框架,在运行时或构建过程中读取和解析注解信息。例如,IDEA可以显示方法是否实现了某个接口的注解信息。 4. **自定义处理器**:开发者可以通过编写注解处理器(Annotation Processor),在编译时动态地处理注解,比如自动生成代码、验证约束等。 至于反编译,Java字节码(.class文件)是可以被反编译成源代码的,这通常用于调试、逆向工程或研究。有许多开源工具可供选择,如JD-GUI、Procyon或 FernFlower等。反编译后得到的源代码可能会失去一些注解相关的元数据,因为注解主要为编译器和特定工具设计,并非为人类阅读优化的文本形式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值