Java注解

注解的语法

通过 @interface 声明一个注解

public @interface RequestMapping {
}

注解的属性

public @interface RequestMapping {
    String value() default "";
}

属性的数据类型包括:

  • 基本数据类型: byte, char, short, int, long, float, double, boolean
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上所有类型的数组

注解的属性定义在语法上类似于接口中的方法, 通过 default 可以设置默认值.

元注解

元注解, 字面上的意思是注解的注解, 就是加在自定义注解上的基础注解. 常用的元注解有以下四种:

(1) @Target

@Target 说明了自定义注解的作用范围, 其取值如下:

  • ElementType.TYPE
    可以注解类、接口或枚举
  • ElementType.FIELD
    可以注解属性
  • ElementType.METHOD
    可以注解方法
  • ElementType.PARAMETER
    可以注解方法内的参数
  • ElementType.CONSTRUCTOR
    可以注解构造方法
  • ElementType.LOCAL_VARIABLE
    可以注解局部变量
  • ElementType.ANNOTATION_TYPE
    可以对另一个一个注解进行注解

我们可以看下Spring中 @Autowired 注解的定义, 它的 @Target 取值有五种.

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

(2) @Retention

@Retention 说明了自定义注解的生命周期, 其取值如下:

  • RetentionPolicy.SOURCE
    注解只存活在源码阶段, 在编译期会被丢弃.
  • RetentionPolicy.CLASS
    注解只会被保留到编译期, 不会被加载到 JVM 中(在运行期被丢弃).
  • RetentionPolicy.RUNTIME
    注解会被加载到 JVM 中, 在程序运行时可以通过反射获取.

Spring中 @Autowired 注解的生命周期就是到运行期, 可以看到它的取值是 RetentionPolicy.RUNTIME.

(3) @Documented

@Documented 指将自定义注解中的属性包含到 Javadoc 中.

(4) @Inherited

@Inherited 说明了自定义注解可以被继承, 当Son类继承了Father类时, 也会继承Father类的注解.

注解的常用API

注解要通过反射来操作. 在开发中一般通过 Class, Field, Method 这三个对象操作注解.

(1) isAnnotationPresent(Class<? extends Annotation> annotationClass)

判断是否存在某个注解.

(2) getAnnotation(Class annotationClass)

获取某个注解.

(3) getAnnotations()

获取所有注解.

注解实例

我们来手动实现下Spring的 @Autowired 注解(简化版), 也就是Spring的 IOC 功能. 如果不熟悉Java反射可以看下这篇博客: https://blog.csdn.net/litianxiang_kaola/article/details/78634822

(1) 定义注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

(2) Service

public class UserService {
    public String getUserName(){
        return "Tyshawn";
    }
}

(3) Controller

public class UserController {
    @Autowired
    private UserService userService;

    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        //定义bean容器, 在Spring中是在应用启动时, 将应用中所有bean实例都存储在bean容器中
        Map<Class<?>, Object> beanMap = new HashMap<>();
        beanMap.put(UserController.class, UserController.class.newInstance());
        beanMap.put(UserService.class, UserService.class.newInstance());

        //实现IOC
        //遍历bean容器, 如果存在成员变量且带有@Autowired注解, 则为成员变量注入实例
        for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
            Class<?> beanClass = beanEntry.getKey();
            Object beanInstance = beanEntry.getValue();

            //获取bean的成员变量
            Field[] beanFields = beanClass.getDeclaredFields();
            //遍历bean的成员变量
            if (beanFields != null && beanFields.length !=0) {
                for (Field beanField : beanFields) {
                    if (beanField.isAnnotationPresent(Autowired.class)) { //判断是否带Autowired注解
                        Class<?> beanFieldClass = beanField.getType();
                        Object beanFieldInstance = beanMap.get(beanFieldClass);
                        //为成员变量注入实例
                        beanField.set(beanInstance, beanFieldInstance);
                    }
                }
            }
        }

        //调用Controller里的Service成员变量
        UserController userController = (UserController) beanMap.get(UserController.class);
        System.out.println(userController.userService.getUserName()); //Tyshawn
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值