Java注解的基本概念和原理及其简单实用
一、注解的基本概念和原理及其简单实用
注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解来使用这些数据),用来将任何的信息或者元数据与程序元素(类、方法、成员变量等)进行关联。其实就是更加直观更加明了的说明,这些说明信息与程序业务逻辑没有关系,并且是供指定的工具或框架使用的。Annotation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的申明语句中。
Annotation其实是一种接口。通过Java的反射机制相关的API来访问Annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。Java语言解释器在工作时会忽略这些Annotation,因此在JVM中这些Annotation是“不起作用”的,只能通过配套的工具才能对这些Annotation类型的信息进行访问和处理。
Annotation和interface的异同:
1、 annotition的类型使用关键字@interface而不是interface。它继承了java.lang.annotition.Annotition接口,并非申明了一个interface。
2、 Annotation类型、方法定义是独特的、受限制的。Annotation类型的方法必须申明为无参数、无异常抛出的。这些方法定义了Annotation的成员:方法名称为了成员名,而方法返回值称为了成员的类型。而方法返回值必须为primitive类型、Class类型、枚举类型、Annotation类型或者由前面类型之一作为元素的一位数组。方法的后面可以使用default和一个默认数值来申明成员的默认值,null不能作为成员的默认值,这与我们在非Annotation类型中定义方法有很大不同。Annotation类型和他的方法不能使用Annotation类型的参数,成员不能是generic。只有返回值类型是Class的方法可以在Annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
参考链接:https://blog.csdn.net/u010987379/article/details/52152795
3、 Annotation类型又与接口有着近似之处。它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
* 元注解@Target,@Retention,@Documented,@Inherited 
* 
* @Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括: 
* ElemenetType.CONSTRUCTOR 构造器声明 
* ElemenetType.FIELD 域声明(包括 enum 实例) 
* ElemenetType.LOCAL_VARIABLE 局部变量声明 
* ElemenetType.METHOD 方法声明 
* ElemenetType.PACKAGE 包声明 
* ElemenetType.PARAMETER 参数声明 
* ElemenetType.TYPE 类,接口(包括注解类型)或enum声明 
* 
* @Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括: 
* RetentionPolicy.SOURCE 注解将被编译器丢弃 
* RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 
* RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 
* 
* @Documented 将此注解包含在 javadoc 中 
* 
* @Inherited 允许子类继承父类中的注解
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Inherited
下面的示例来简单的讲述spring注解原理:
本例实现了在set方法上和在字段属性上注解的处理解析。
1、定义注解
- package com.yt.annotation;
 - import java.lang.annotation.ElementType;
 - import java.lang.annotation.Retention;
 - import java.lang.annotation.RetentionPolicy;
 - import java.lang.annotation.Target;
 - /**
 - * @Description:定义注解
 - * @ClassName: ZxfResource
 - * @Project: spring-aop
 - * @Author: zxf
 - * @Date: 2011-6-7
 - */
 - // 在运行时执行
 - @Retention(RetentionPolicy.RUNTIME)
 - // 注解适用地方(字段和方法)
 - @Target({ ElementType.FIELD, ElementType.METHOD })
 - public @interface ZxfResource {
 - //注解的name属性
 - public String name() default "";
 - }
 
2、带有注解的服务类
- package com.yt.annotation;
 - /**
 - * @Description: 带有注解的服务
 - * @ClassName: UserDaoImpl
 - * @Project: spring-aop
 - * @Author: zxf
 - * @Date: 2011-6-7
 - */
 - public class UserServiceImpl {
 - public UserDaoImpl userDao;
 - public User1DaoImpl user1Dao;
 - // 字段上的注解,可以配置name属性
 - @ZxfResource
 - public User2DaoImpl user2Dao;
 - // set方法上的注解,带有name属性
 - @ZxfResource(name = "userDao")
 - public void setUserDao(UserDaoImpl userDao) {
 - this.userDao = userDao;
 - }
 - // set方法上的注解,没有配置name属性
 - @ZxfResource
 - public void setUser1Dao(User1DaoImpl user1Dao) {
 - this.user1Dao = user1Dao;
 - }
 - public void show() {
 - userDao.show();
 - user1Dao.show1();
 - user2Dao.show2();
 - System.out.println("这里是Service方法........");
 - }
 - }
 
3、要注入的DAO
- package com.yt.annotation;
 - /**
 - * @Description: 要注入的DAo类
 - * @ClassName: UserDaoImpl
 - * @Project: spring-aop
 - * @Author: zxf
 - * @Date: 2011-6-7
 - */
 - public class UserDaoImpl {
 - String name ;
 - public void show(){
 - System.out.println("这里是dao方法........");
 - }
 - }
 
- <?xml version="1.0" encoding="UTF-8"?>
 - <beans>
 - <bean id = "userDao" class="com.yt.annotation.UserDaoImpl" />
 - <bean id = "user1Dao" class="com.yt.annotation.User1DaoImpl" />
 - <bean id = "user2Dao" class="com.yt.annotation.User2DaoImpl" />
 - <bean id = "userService" class = "com.yt.annotation.UserServiceImpl" />
 - </beans>
 
4、注解处理器
- package com.yt.annotation;
 - import java.beans.Introspector;
 - import java.beans.PropertyDescriptor;
 - import java.lang.reflect.Field;
 - import java.lang.reflect.Method;
 - import java.util.ArrayList;
 - import java.util.HashMap;
 - import java.util.Iterator;
 - import java.util.List;
 - import java.util.Map;
 - import org.apache.log4j.Logger;
 - import org.dom4j.Document;
 - import org.dom4j.DocumentException;
 - import org.dom4j.Element;
 - import org.dom4j.io.SAXReader;
 - /**
 - * @Description: spring中的注解原理
 - * @ClassName: ClassPathXMLApplicationContext
 - * @Project: spring-aop
 - * @Author: zxf
 - * @Date: 2011-6-3
 - */
 - public class ClassPathXMLApplicationContext {
 - Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class);
 - List<BeanDefine> beanList = new ArrayList<BeanDefine>();
 - Map<String, Object> sigletions = new HashMap<String, Object>();
 - public ClassPathXMLApplicationContext(String fileName) {
 - //读取配置文件中管理的bean
 - this.readXML(fileName);
 - //实例化bean
 - this.instancesBean();
 - //注解处理器
 - this.annotationInject();
 - }
 - /**
 - * 读取Bean配置文件
 - * @param fileName
 - * @return
 - */
 - @SuppressWarnings("unchecked")
 - public void readXML(String fileName) {
 - Document document = null;
 - SAXReader saxReader = new SAXReader();
 - try {
 - ClassLoader classLoader =
 - Thread.currentThread().getContextClassLoader();
 - document = saxReader.read(classLoader.getResourceAsStream(fileName));
 - Element beans = document.getRootElement();
 - for (Iterator<Element> beansList = beans.elementIterator();
 - beansList.hasNext();) {
 - Element element = beansList.next();
 - BeanDefine bean = new BeanDefine(
 - element.attributeValue("id"),
 - element.attributeValue("class"));
 - beanList.add(bean);
 - }
 - } catch (DocumentException e) {
 - log.info("读取配置文件出错....");
 - }
 - }
 - /**
 - * 实例化Bean
 - */
 - public void instancesBean() {
 - for (BeanDefine bean : beanList) {
 - try {
 - sigletions.put(bean.getId(),
 - Class.forName(bean.getClassName()).newInstance());
 - } catch (Exception e) {
 - log.info("实例化Bean出错...");
 - }
 - }
 - }
 - /**
 - * 注解处理器
 - * 如果注解ZxfResource配置了name属性,则根据name所指定的名称获取要注入的实例引用,
 - * 如果注解ZxfResource;没有配置name属性,则根据属性所属类型来扫描配置文件获取要
 - * 注入的实例引用
 - *
 - */
 - public void annotationInject(){
 - for(String beanName:sigletions.keySet()){
 - Object bean = sigletions.get(beanName);
 - if(bean!=null){
 - this.propertyAnnotation(bean);
 - this.fieldAnnotation(bean);
 - }
 - }
 - }
 - /**
 - * 处理在set方法加入的注解
 - * @param bean 处理的bean
 - */
 - public void propertyAnnotation(Object bean){
 - try {
 - //获取其属性的描述
 - PropertyDescriptor[] ps =
 - Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
 - for(PropertyDescriptor proderdesc : ps){
 - //获取所有set方法
 - Method setter = proderdesc.getWriteMethod();
 - //判断set方法是否定义了注解
 - if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){
 - //获取当前注解,并判断name属性是否为空
 - ZxfResource resource = setter.getAnnotation(ZxfResource.class);
 - String name ="";
 - Object value = null;
 - if(resource.name()!=null&&!"".equals(resource.name())){
 - //获取注解的name属性的内容
 - name = resource.name();
 - value = sigletions.get(name);
 - }else{ //如果当前注解没有指定name属性,则根据类型进行匹配
 - for(String key : sigletions.keySet()){
 - //判断当前属性所属的类型是否在配置文件中存在
 - if(proderdesc.getPropertyType().isAssignableFrom(sigletions.get(key).getClass())){
 - //获取类型匹配的实例对象
 - value = sigletions.get(key);
 - break;
 - }
 - }
 - }
 - //允许访问private方法
 - setter.setAccessible(true);
 - //把引用对象注入属性
 - setter.invoke(bean, value);
 - }
 - }
 - } catch (Exception e) {
 - log.info("set方法注解解析异常..........");
 - }
 - }
 - /**
 - * 处理在字段上的注解
 - * @param bean 处理的bean
 - */
 - public void fieldAnnotation(Object bean){
 - try {
 - //获取其全部的字段描述
 - Field[] fields = bean.getClass().getFields();
 - for(Field f : fields){
 - if(f!=null && f.isAnnotationPresent(ZxfResource.class)){
 - ZxfResource resource = f.getAnnotation(ZxfResource.class);
 - String name ="";
 - Object value = null;
 - if(resource.name()!=null&&!"".equals(resource.name())){
 - name = resource.name();
 - value = sigletions.get(name);
 - }else{
 - for(String key : sigletions.keySet()){
 - //判断当前属性所属的类型是否在配置文件中存在
 - if(f.getType().isAssignableFrom(sigletions.get(key).getClass())){
 - //获取类型匹配的实例对象
 - value = sigletions.get(key);
 - break;
 - }
 - }
 - }
 - //允许访问private字段
 - f.setAccessible(true);
 - //把引用对象注入属性
 - f.set(bean, value);
 - }
 - }
 - } catch (Exception e) {
 - log.info("字段注解解析异常..........");
 - }
 - }
 - /**
 - * 获取Map中的对应的bean实例
 - * @param beanId
 - * @return
 - */
 - public Object getBean(String beanId) {
 - return sigletions.get(beanId);
 - }
 - public static void main(String[] args) {
 - ClassPathXMLApplicationContext path = new ClassPathXMLApplicationContext(
 - "configAnnotation.xml");
 - UserServiceImpl userService =(UserServiceImpl)path.getBean("userService");
 - userService.show();
 - }
 - }
 
Java注解的基本概念和原理及其简单实用的更多相关文章
- SpringInAction--自动化装配(显示装配之 java注解配置)
		
Spring在配置时候有三种方案可选 1.在xml中进行显示配置 2.在java中进行显示配置 3.隐式的Bean发现机制和自动装配 今天学习的 第二种—— 在java中进行显示配置 场景: 尽管在很 ...
 - Java中的泛型 (上) - 基本概念和原理
		
本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...
 - Java线程:概念与原理
		
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
 - Java IO学习笔记:概念与原理
		
Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了 ...
 - 认识下java注解的实现原理
		
1,什么是注解 注解也叫元数据,例如常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注 ...
 - Java编程的逻辑 (35) - 泛型 (上) - 基本概念和原理
		
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
 - Java 注解的概念与种类
		
Java 注解的概念与种类 一,什么是注解 注解和XML文件都是常用的,对web项目进行配置性描述的方式. 举个最简单的例子,对于一个Servlet,比如LoginServlet,采用如下方式: @W ...
 - java@ 注解原理与使用
		
Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对 ...
 - Java注解处理器(转)
		
Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...
 
随机推荐
- CH#46A 磁力块
			
题意 磁力块 CH Round #46 - 「Adera 8」杯NOI模拟赛 描述 在一片广袤无垠的原野上,散落着N块磁石.每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐 ...
 - 写一个小程序实现win系统定时锁屏
			
貌似很久没写程序了,随便用C语言实现吧 #include<stdio.h> #include<stdlib.h> int main(){ system("rundll ...
 - expect脚本实例
			
#!/usr/bin/expect //必须写这句,表明使用expect,有些系统可能没有自带,使用yum install expect -y 安装 spawn ssh 192.168.2.128 / ...
 - Tomcat三种项目部署方式
			
第一种:直接将项目放在webapps目录下 材料:项目文件名hello,文件hello.html如图: 访问地址: 注释:hello 项目文件名 hello.html 访问的文件名字 第二种:修改c ...
 - oracle故障解决
			
修改了字符集,修改错了,然后不能启动 alter system set nls_language='AMERICA'; shutdown immediate; startup 报错 [oracle@o ...
 - TweenMax 动画库,知识点
			
官方地址:https://greensock.com/tweenmax github 地址:https://github.com/greensock/GreenSock-JS 比较好的介绍文章: ht ...
 - Python应用场景 (转)
			
Web应用开发 Python经常被用于Web开发.比如,通过mod_wsgi模块,Apache可以运行用Python编写的Web程序.Python定义了WSGI标准应用接口来协调Http服务器与基于P ...
 - golang bug Unknown load command 0x32 (50)
			
问题 编译文件时报错: /usr/local/go/pkg/tool/darwin_amd64/link: /usr/local/go/pkg/tool/darwin_amd64/link: comb ...
 - JSON C# Class Generator ---由json字符串生成C#实体类的工具
			
json作为互联网上轻量便捷的数据传输格式,越来越受到重视.但在服务器端编程过程中,我们常常希望能通过智能提示来提高编码效率.JSON C# Class Generator 能将json格式所表示的J ...
 - HADOOP1.X中HDFS工作原理
			
转载自:http://www.daniubiji.cn/archives/596 HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据googl ...