再说注解

再说注解

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

全栈程序员社区此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“全栈程序员社区”或者“www_javaforall_cn”或者微信扫描右侧二维码都可以关注本站微信公众号。

    当今的各种框架:Hibernate、Struts、Spring等,包含EJB,都支持注解形式,注解相比XML配置而言确实更为简洁,先来说说关于注解”what is”的问题。

注解

    从形式上看,注解是类似凝视,它为代码提供了一种新的标识方式,能够在编译器先定义、使用,等到执行时再去解析这些注解相应的含义。在JDK1.5中引入,如今的JDK已经把注解的地位提升到和二进制码同样,当然假设你略微关注过注解,你应该知道注解解析过程的基础是反射原理。

    它为什么能够使用反射原理?对照类载入使用反射可知,虚拟机在载入class文件时,也会为注解分配空间并解析,终于还会为注解和相应的二进制码建立关联,这就为使用反射提供了基础。

    注解不过用于标注,并不会主动执行,也不会影响主代码的逻辑,只起到辅助性的作用,但其对代码的说明能力,结合反射技术已经给了我们非常大的想象空间。


    从宏观上看,注解的运行共分为3部分:

  • 定义注解
  • 使用注解
  • 解析注解

    定义注解

    说到定义注解须要先说一下元注解,即定义注解的注解,共同拥有四种:@Retention @Target @Document @Inherited:

  • @Retention:注解的生命时长:编译期、执行期……
  • @Target:应用位置:字段、方法、类……
  • @Documented:是否被包括在javadoc中
  • @Inherited:子类能否够继承父类该注解

    有关这几个元注解的说明不再细说,有兴趣能够查看元注解的源代码,位于java.lang.annotation下,另有部分注解位于javax.annotation下。

    使用注解

    使用注解的方式非经常见也非常简答,如@MyAnnotation(ElementType.RealNew),将此注解加到类、字段、方法等上即表明此注解关联到该类的指定项上。

    解析注解

    这三步中,事实上这是最后也是最关键的一步,上面定义、使用再好,没有一个专门解析注解的类,前面都是白写,解析注解实例会在以下说明,解析的核心步骤是:

  • 得到使用注解的类
  • 使用反射得到类中的字段、方法等
  • 得到使用了指定注解的方法、字段等,及其注解的值
  • 编写一个函数,依据注解类型及注解值进行指定操作

实例

    依据以上所说,编写了一个注解实例,实例内容为:当检測到House属性中有我们自己定义的注解时,向House注入一个Dog。

    文件说明

  • NewMePolicy:定义一个枚举,指定注解能够使用的參数
  • NewMeAnnotation:定义一个注解
  • Dog:辅助使用注解的类
  • House:使用我们自己定义注解的类
  • TestAnnotation:解析注解的类

    NewMePolicy

package annotation;

public enum NewMePolicy {

	//使用单例模式获取对象
	Singleton,
	//创建新对象
	RealNew,
	//忽视此注解
	Ignore
}

    NewMeAnnotation

package annotation;

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

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NewMeAnnotation {
	NewMePolicy category();
	public String className();
}

    House

package annotation;

public class House {

	@NewMeAnnotation(category=NewMePolicy.RealNew,className="annotation.Dog")
	private Class<?> cat;
	
	private String other;
        
        // 省略getter和setter方法

}

    TestAnnotation

package annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;

public class TestAnnotation {

	public static void main(String [] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException
	{
		//定义一个暂时的HashMap,用于保存全部涉及到的用户自己定义类实例
		HashMap<String, Object> temp=new HashMap<String, Object>();
		//定义另外一个HashMap,用于保存处理过的用户自己定义类实例
		HashMap<String, Object> objMap=new HashMap<String, Object>();
		//载入House类
		Class<?> uaClass=Class.forName("annotation.House");
		//利用反射得到其全部的属性
		Field[] fields=uaClass.getDeclaredFields();
		//遍历得到的属性
		for (Field field:fields) {
			//该字段是否使用了我们自己定义的注解
			boolean hasAnnotation=field.isAnnotationPresent((Class<? extends Annotation>) NewMeAnnotation.class);
			if (hasAnnotation) {
				//得到有NewMeAnnotation注解的字段
				NewMeAnnotation annotations=field.getAnnotation(NewMeAnnotation.class);
				//打印查看注解实例化的策略
				System.out.println("注入的策略为: "+annotations.category());
				//打印要注入的内容
				System.out.println("注入的类为: "+annotations.className());
				if (NewMePolicy.RealNew.equals(annotations.category())) {
					//找到相应的类,实例化
					Class<?> cat=Class.forName(annotations.className().toString());
					House house= (House) uaClass.newInstance();
					//将两个类的实例保存到temp中
					temp.put(uaClass.toString(), house);
					temp.put(Dog.class.toString(), cat);
					//注入实例
					house.setCat(cat);
					//保存定义好的UseAnnotation实例
					objMap.put(uaClass.toString(), house);
				}
				
				System.out.println("类: "+uaClass+"已经完毕初始化");
			}
			else {
				System.out.println("字段:"+field+" 没有NewMeAnnotation注解!");
			}
		}
	}
}

    控制台输出

注入的策略为: RealNew
注入的类为: annotation.Dog
类: class annotation.House已经完毕初始化
字段:private java.lang.String annotation.House.other 没有NewMeAnnotation注解!

    能够看到,我们能够使用反射获取到字段,及字段的注解,依据注解内容,我们能够动态的将注解规定的类Dog注入到House中,当然这个样例在解析的时候还不是非常全,比方没有解析假设注解的category为singleton、Ignore时怎样处理,可是作为一个解释注解的样例,我觉得足够了。

总结

    这个注解的样例是使用setter将一个bean注入到另外一个bean中,有没有认为有些眼熟,对Spring,稍后的文章会解释Spring是怎样依据注解管理bean之间的关系。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117896.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • latex参考文献上标怎么打_latex的上下角标

    latex参考文献上标怎么打_latex的上下角标1、使用\supercite{}2、加入以下语句,引用时直接使用\cite{}原文链接:https://www.latexstudio.net/archives/7686.html\makeatletter\def\@cite#1#2{\textsuperscript{[{#1\if@tempswa,#2\fi}]}}\makeatother

    2025年10月10日
    3
  • 前端开发常用网站_软件开发领域知识

    前端开发常用网站_软件开发领域知识87个前端必备开发网站来源:https://zhuanlan.zhihu.com/p/86777413来源:https://zhuanlan.zhihu.com/p/86777413来源:htt

    2022年8月3日
    10
  • 邮箱正则校验[通俗易懂]

    邮箱正则校验[通俗易懂]”^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$”这个是一个企业级的程序里copy出来的。合法E-mail地址:1.必须包含一个并且只有一个符号“@”2.第一个字符不得是“@”或者“.”3.不允许出现“@.”或者.@4.结尾不得是字符“@”或者“.”…

    2022年6月15日
    56
  • mt4交易系统源码_如何将源码加载到mt4里面

    mt4交易系统源码_如何将源码加载到mt4里面1、打开编辑器:第二步,新建一个指标或者eaqml4文件.第三步创建一个ea文件:点击下一步:命名,aaa,点击下一步:全部不打勾,点击下一步:全部不打勾,点击完成:然后全部选中,删除代码:然后选中源码,复制到aaa里面,然后点击编写:就可以在ea里面找到你复制的ea了。指标的源码跟ea的一样,只需要建立一个指标文件,然后复制进去就可以了。如果觉得文章对你有帮助,可以关注公众号,谢谢您…

    2022年5月30日
    90
  • mysql8分区表_MySQL 分区表[通俗易懂]

    mysql8分区表_MySQL 分区表[通俗易懂]MySQL分区就是将一个表分解为多个更小的表。从逻辑上讲,只有一个表或一个索引,但在物理上这个表或者索引可能由多个物理分区组成。每个分区在物理上都是独立的。MySQL数据库分区类型:Range分区:行数据基于属于一个给定连续区间的列值放入分区。List分区:和Range分区类似,只是List分区面向的是离散的值。Hash分区:根据用户自定义的表达式的返回值来进行分区,返回值不能为负数。Key分区:…

    2022年6月11日
    44
  • 大数据建模步骤有哪些

    大数据建模步骤有哪些  数据建模,通俗地说,就是通过建立数据科学模型的手段解决现实问题的过程。数据建模也可以称为数据科学项目的过程,并且这个过程是周期性循环的,也是是我们在做数据分析的时候会经常使用的一种数据分析方法,那么大数据建模都有哪些步骤。  1)数据测量  数据测量包括ECU内部数据获取,车内总线数据获取以及模拟量数据获取,特别是对于新能源汽车电机、逆变器和整流器等设备频率高达100KHz的信号测量,ETAS提供完整的解决方案。  2)大数据管理与分析  目前的汽车嵌入式控制系统…

    2022年4月30日
    117

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号