【JAVA】使用自定义注解简易模拟Spring中的自动装配@Autowired

版权声明:转载请注明 https://blog.csdn.net/qq_33591903/article/details/82180745

            使用自定义注解简易模拟Spring中的自动装配@Autowired

我们在学Spring的时候,常常需要配置大量的bean,由Spring进行管理,这就导致配置文件的膨胀,后来使用到@Autowired注解,才发现到注解的强大,那么底层是怎么实现的呢?碍于博主才疏学浅,不能带着大家深入源码进行探讨,今天我们就用自定义注解的方式来模拟一下@Autowired。

一、什么是注解

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

JDK中自带了几个注解,比如@Override,这是一个标识注解,注解内部没有属性,用来标注此方法是重写方法。还有@Deprecated,同样也是标识注解,用来告知此方法已经过时。如果我们仍然使用此方法,又想消除编译器弹出的过时警告,可以写上@SuppressWarnings("deprecation"),就可以消除警告提示。

 

二、注解内部属性

以下是示例代码:

package day0829;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TestAnnotation {
    String name();

    int age() default 18;
}

(1)使用@interface关键字来定义注解

(2)成员变量以无参数无异常的方式声明

(3)可以用default为成员变量指定默认值

(4)成员类型只能是原始数据类型、String、Class、Annotation、Enumeration

(5)注解可以没有成员,没有注解的成员称为标识注解


@Target、@Retention、@Inherited、@Documented等都是元注解。

元注解,即对注解的注解。要会自定义注解,必须了解注解头部的元注解。

(1)@Target,注解的作用域,即此注解应该被用在什么地方

属性名

声明地方

ElementType.CONSTRUCTOR

 

构造方法

ElementType.FIELD

 

字段

ElementType.LOCAL_VARIABLE

 

局部变量

ElementType.METHOD

 

方法

ElementType.PACKAGE

 

ElementType.PARAMETER

 

参数

ElementType.TYPE

 

类、接口

(2)@Retention,注解的生命周期,即注解在什么范围内有效

属性名

生命周期说明

RetentionPolicy.SOURCE

 

只在源码内显示,编译时则丢弃

RetentionPolicy.CLASS

 

编译时会记录到class文件中,运行时忽略

RetentionPolicy.RUNTIME

 

运行时存在,通过反射读取注解

(3)@Inherited,标识注解,允许子类继承

注意:此元注解所在的注解只能在放在类上,放在接口上则不起作用。

(4)@Documented,标识注解,生成javadoc文档时,会包含此注解

 

那么注解如何解析呢?我们把解析注解的过程放入到案例中来

 

三、使用自定义注解实现简易的自动装配

注解代码示例:

package day0829;

import java.lang.annotation.*;

//只用在字段上
@Target({ElementType.FIELD})
//运行时有效,这样可以通过反射解析注解
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    int value() default 0;
}

解析注解示例:

package day0829;

import java.lang.reflect.Field;

public class Test {
    @TestAnnotation(2)
    private static int value;
    private int a = 1;

    public static void main(String args[]) throws IllegalAccessException {
        //获取所有变量
        Field[] fields = Test.class.getDeclaredFields();
        for (Field field : fields) {
            //允许访问私有变量
            field.setAccessible(true);
            //判断此变量是否使用了注解
            boolean isUsedAnnotation = field.isAnnotationPresent(TestAnnotation.class);
            if (isUsedAnnotation) {
                TestAnnotation annotation = field.getAnnotation(TestAnnotation.class);
                //按照指定的注解value,给变量赋值
                field.set(annotation, annotation.value());
            }
        }
        //输出变量的值
        System.out.println("Test中变量a的值为"+value);
    }
}

最后输出:

可见达到了预期的属性装配目的

猜你喜欢

转载自blog.csdn.net/qq_33591903/article/details/82180745