再说注解

再说注解

大家好,又见面了,我是全栈君,今天给大家准备了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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • U41492 树上数颜色(dsu)「建议收藏」

    U41492 树上数颜色(dsu)「建议收藏」U41492树上数颜色题意:输入n(1e5)n(1e5)n(1e5)表示一棵根为1的树有nnn个节点接下来n−1n-1n−1行每行u,vu,vu,v表示树边接下来一行nnn个数,c1,c2,…,cn(1≤ci≤n)c_1,c_2,\dots,c_n(1\leqc_i\leqn)c1​,c2​,…,cn​(1≤ci​≤n)表示节点颜色接下来m(m≤n)m(m\leqn)m(m≤n)…

    2025年6月15日
    2
  • jboss安装与配置_微信最新版下载并安装

    jboss安装与配置_微信最新版下载并安装jboss有开源和商业两个版本,他们区别如下:JBossAS开源社区版本,发布比较频繁。JBoss7,先后发布了7.0.0,7.0.1,7.0.2,7.1.0,7.1.1,7.1.2,7.1.3,7.2.0,其中7.1.1比较经典,7.2.0是JBossEAP6.1的基础,但7.1.2,7.1.3,7.2.0只是源代码打了Tag,并没提供开放下载。JBossEAP(EnterpriseApplicationPlatform)在开源版本上构建的企业版本,目

    2022年10月3日
    3
  • RedFlag Linux 5.0桌面版安装oralce10[通俗易懂]

    RedFlag Linux 5.0桌面版安装oralce10[通俗易懂] 本文中描述的步骤可能有些不是必须的,但笔者没有进一步验证,故将安装过程中的所有步骤均列出在此。—www.bianceng.cn1.安装RedflagLinux5.0桌面版2.安装前得准备,打几个补丁1).redhatlinux9下第一张光盘下的RedHat/RPMS/compat-libstdc++-7.3-2.96.118.i386.rpm(安装方法rpm-ivh

    2022年8月20日
    6
  • D3js快速入门——用最新版D3js实现树图

    D3js快速入门——用最新版D3js实现树图文章目录 引言 1 D3js 是什么 2 D3js 相对其他数据可视化方案的优势 2 1SVG 对比 Canvas2 2D3 js 对比 Echarts3 怎么用 D3 js 开发一个树图 3 1 前置基础 3 2d3 开发树图流程 3 3 动手实现一个树图 3 3 1 普通 tidetree3 3 2 你的树图不简单 radiotidetre 3 3 更多可能 更多类型的树图引言上周我们组新开项目 技术调研之后决定使用 d3 js 做数据可视化开发 mentor 让我来做初期技术调研 之后的技

    2025年10月24日
    2
  • 如何添加smtp服务器_smtp服务器设置

    如何添加smtp服务器_smtp服务器设置在现在这个时代中,人们传输信息基本上都是用邮件传输,那么你知道电脑之间是怎么用邮件传输的么。就是通过smtp服务器,通过这个服务器,人们可以把自己写的东西通过邮件经过这个服务器传输到你想让邮件传输到的地方,接下来就让小编好好给大家介绍一下。Smtp传输器是什么?Smpt的意思是简单的邮件传输协议,它是一组用于源地址到目的地传送邮件的规则,并且由它决定邮件的中转方式。Smtp传输器使用由tcp提供的…

    2022年9月1日
    3
  • DOM attributes and properties

    DOM attributes and properties

    2022年1月9日
    39

发表回复

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

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