栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

神奇的注解是怎么实现的,你不好奇吗?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

神奇的注解是怎么实现的,你不好奇吗?

大家好浪,我是下雨了睡觉,最近学完 java的ssm框架之后,我有了好多的领悟,许多非常值得学习的思想,其中还有一个让我疑惑的就是框架中推荐的注解式开发,添加一条注解就可以自动注入,哇哇哇……此处省略一万字,它好神奇啊,我想看看它的全貌,点进源码,我蒙了,很短,并不是我想的一堆逻辑处理,于是就查资料学习,总结了以下知识点,一起来学习吧!芜湖,拿下它 


文章目录

离不开的知识:反射机制浪java反射快速入门‍写一个注解,从而理解它总结结语


离不开的知识:反射机制浪

Java开始是静态强类型语言,类型是静态的

优点

避免了程序在运行时发生变量类型相关的错误,代码更健壮,提前知道类型,编译器可以针对这些信息进行优化,从而提升程序的执行速度

缺点

程序员要注意变量的类型,变量的声明会使得代码量增加

Java语言为了使用社会需求,Java在静态的基础之上引入了反射机制使得自己具有一定的动态性,这使得Java语言更加灵活,也因此诞生了大名鼎鼎的spring框架等等

java反射快速入门‍

提一个需求,要求不修改源码,通过配置文件决定实例化哪个对象,Ok

bean.properties配置文件

bean=com.liu.annotation_.Dog

Dog类

package com.liu.annotation_;

public class Dog {
    private Integer id = 1;
    private String name = "小猫";
}

Cat类

package com.liu.annotation_;

public class Cat {
    private Integer id = 1;
    private String name = "小狗";
}

Test类

package com.liu.annotation_;

import java.io.IOException;
import java.util.Properties;

public class Test {
    private static Properties properties;
    static {
        properties = new Properties();
        try {
            
            properties.load(Test.class.getClassLoader().getResourceAsStream("bean.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception{
        
        String bean = properties.getProperty("bean");
        
        Object o = Class.forName(bean).newInstance();
        System.out.println(o.getClass()); 
    }
}

当配置文件是bean=com.liu.annotation_.Dog时,输出

当配置文件是bean=com.liu.annotation_.Cat时,输出

这就完成了在不修改源码的情况下,动态改变了实例化的对象,使得程序变得更灵活……
它也是很多框架的基础,其中注解也有用到它哦,下面开始注解的解析


写一个注解,从而理解它

自定义MyComponent 注解

package com.liu.annotation_;

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


@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)
public @interface MyComponent {
}

自定义MyValue 注解

package com.liu.annotation_;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
    String value();
}

给cat类添加自定义注解

package com.liu.annotation_;

@MyComponent
public class Cat {

    @MyValue("0")
    private Integer id;
    @MyValue("招财猫")
    private String name;

    @Override
    public String toString() {
        return "Cat{" +
                "id=" + id +
                ", name='" + name + ''' +
                '}';
    }
}

使用我们自定义的注解 核心

package com.liu.annotation_;

import java.lang.reflect.Field;

public class TestMyAnnotation {
    public static void main(String[] args) throws Exception {
        
        Class catClass = Cat.class;
        
        MyComponent annotation = catClass.getAnnotation(MyComponent.class);
        
        if(annotation != null){
            System.out.println("添加了 MyComponent 注解");
            
            Cat cat = Cat.class.newInstance();
            
            System.out.println(cat);
            Field[] declaredFields = catClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                MyValue valueAnnotation = declaredField.getAnnotation(MyValue.class);
                if(valueAnnotation != null){
                    System.out.println(valueAnnotation + "添加了 value 注解");
                    
                    String value = valueAnnotation.value();
                    System.out.println("注解添加的值是:" + value);
                    
                    declaredField.setAccessible(true);
                    
                    if(declaredField.getType().getName().equals("java.lang.Integer")){
                        Integer val = Integer.parseInt(value);
                        declaredField.set(cat,val);
                    }else{
                        declaredField.set(cat,value);
                    }
                }
            }
            System.out.println("最终效果---------------");
            System.out.println(cat);
        }else{
            System.out.println("没有添加 MyComponent 注解");
            
        }
    }
}

运行结果,成功赋值

添加了 MyComponent 注解
Cat{id=null, name='null'}
@com.liu.annotation_.MyValue(value=0)添加了 value 注解
注解添加的值是:0
@com.liu.annotation_.MyValue(value=招财猫)添加了 value 注解
注解添加的值是:招财猫
最终效果---------------
Cat{id=0, name='招财猫'}

总结

利用反射机制以及提供的getAnnotation()方法可以获取我们自定义的注解对象,再经过简单判断是否添加,如果添加了@MyComponent,就创建对象,如果没有则不添加,再经过反射机制获取所有字段以及通过getAnnotation()方法循环判断是否添加了自定义的@MyValue注解,如果有就给它赋值,但是有一个问题,字段是私有属性,按理说是无法直接赋值的,确实如此,不过,我们可以通过Java提供的反射爆破,越过检查,从而完成私有属性的直接赋值,只需要一行代码declaredField.setAccessible(true);即可,另外在赋值时判断一下待赋值的字段的类型,然后再根据类型分别赋值就了,其实也是很简单的,但是这种思想真的很有意思,值得思考和借鉴,因此,我相信你对Java中神奇的注解有了初步的了解,这对你学习框架很有帮助

结语

我是下雨了睡觉,这就是全部内容了,创造不易梁,有用的话点个赞怕類


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/762411.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号