扯扯注解的蛋

为什么学习注解?学习注解有什么好处?学完能做什么?
1、能够读懂别人的代码,特别是框架相关的代码
2、让编程更加简洁,代码更加清晰
3、让别人高看你一眼 注解是java1.5引入的
概念:
java人提供了一种原程序中的元素关联任何消息和任何元数据的途径和方法 java中的常见注解
JDK自带注解:
@Override
放在方法前,表示该方法重写了父类的这个方法
@Deprecated
放在方法上,表名该方法已经过时,后面还使用这个方法会弹出黄色警告线
@SuppressWarnings("deprecation")
放在方法前,忽视警告 常见的第三方注解:
Spring:
@Autowired 自动装载该属性
@Service
@Repository
Mybatis:
@InsertProvider
@UpdateProvider
@Options 注解的分类
按运行机制分:
源码注解:注解只在源码中存在,编译成class文件后就不存在了
编译时注解:注解种子源码和class文件都存在。我们使用的三个JDK注解都是编译时注解
运行时注解:运行阶段还会起作用,甚至会影响运行逻辑的注解 例如spring的@autowried 元注解:注解的注解
自定义注解
自定义注解的语法要求
注解的注解(元注解)
使用自定义注解
解析注解
概念:通过反射获取类、函数或成员上运行的注解信息,从而实现动态控制程序运行的逻辑
注解应用实战

一个注解的例子和一些概念:

//一个注解的例子

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description{
String desc();
String author();
int age() default 18;
} //1.使用@interface关键字定义注解
//2.成员以无参无异常的方式声明 可以给成员指定默认值,比如age
//3、成员类型是受限的,合法的类型包括原始类型以及String,Class,Annotation,Enumeration
//4.如果注解只有一个成员,则成员必须取名为value(),在使用时可以忽略成员名和赋值号(=)
//5.注解类可以没有成员,没有成员的注解成为标识注解 /**
元注解:用在注解上的注解
@Target 注解使用的一个作用域,多个用逗号隔开,它的可选值:
CONSTRUCTOR构造方法声明
FIELD 字段声明
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类,接口
例子:
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention 注解的声明周期,可选属性
SOURCE 只在源码显示,编译时会丢弃
CLASS 编译时会记录到class中,运行时忽略
RUNTIME 运行时存在,可以通过反射读取
例子:
@Retention(RetebtionPolicy.RUNTIME) @Inherited 标识注解,允许子注解继承它
@Document 也是标识注解,生成doc的时候回包含注解信息
*/ /**
使用自定义注解
使用注解的语法:
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,...)
例子:
@Desciption(desc="I am eyeColor",author="Mooc body",age=18)
public String eyeColor(){
return "red";
}
*/

接触了解简单注解:

package com.ann.test;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
String desc();
String author();
int age() default 18;
}
/*
* 当注解使用在不符合类型的场合的时候,会发生编译期错误
* 如果Retention注解的值是SOURCE或者CLASS时,使用反射解析注解会得不到,因为反射是得到的是运行期的Class文件
* @Inherited是个标识注解表名注解可以继承
* 我发现直接解析Child上面的注解的话是无法的到任何注解的,说明它并没有继承Person类的注解,这是为什么呢?
* If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration,
* and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type.
* 注解是应该声明在class上的
* 我们将Person更改为class,则发现可以在子类得到其类上面的注解,但是,其方法上的注解是无法继承得到的,所以我们没有获取到
*/ package com.ann.test;
@Description(author="guozhen",desc="I am a interface annotion!",age=22)
public class Person {
public String name(){
return null;
}
@Description(author="I am a method annotation!",desc="haha",age=22)
public int age(){
return 0;
}
//我发现并不是所有的人都会唱歌,所以这个sing()不应该写在这里,但是有人实现了这个接口不能改动
@Deprecated //表示这个方法已经过时
public void sing(){ }
}
package com.ann.test; public class Child extends Person { @Override
public String name() {
// TODO Auto-generated method stub
return null;
} @Override
public int age() {
// TODO Auto-generated method stub
return 0;
} @Override
public void sing() {
// TODO Auto-generated method stub } } package com.ann.test; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; public class Test {
public static void main(String[] args) {
//解析注解。
//1.首先找到装载了注解的class文件
try {
Class c=Class.forName("com.ann.test.Child");
//2判断类上是否存在指定注解
boolean isExit=c.isAnnotationPresent(Description.class);
if(isExit){
//3.得到注解并输出其内容
Description d=(Description)c.getAnnotation(Description.class);
System.out.println(d.author()+"\t"+d.age()+"\t"+d.desc());
}
//解析方法上的注解
//1.得到方法
Method[] ms=c.getMethods();
for(Method m:ms){
isExit=m.isAnnotationPresent(Description.class);
if(isExit){
Description d=(Description)m.getAnnotation(Description.class);
System.out.println(d.author()+"\t"+d.age()+"\t"+d.desc());
}
Annotation[] as=m.getAnnotations();
for(Annotation a:as){
if(a instanceof Description){
Description ds=(Description)a;
System.out.println(ds.author()+"\t"+ds.age()+"\t"+ds.desc());
}
}
}
//2.或者也可以这样解析方法上的注解 } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
public void sing(){
Person p=new Child();
p.sing();//这个方法已经过时,虽然可以使用,但是会给警告。我们可以添加注解使得忽视警告
}
// @Description(desc="I am eyeColor",author="Moocbocy",age=18)
public String eteColor(){
return "red";
}
}

小小实战,加深理解:

package com.ann.test;

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 Table {
String value();
}
package com.ann.test; 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 Column {
String value();
}
package com.ann.test;
/**
*
* @author Administrator
* 我们要操作的是Student表
* 里面有这些字段:
* id name age sex email
*/
@Table("Student")
public class Student {
@Column("id")
private int id;
@Column("username")
private String name;
@Column("age")
private int age;
@Column("sex")
private String sex;
@Column("email")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
} }
package com.ann.test; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; /**
*
* @author Administrator
* 通过一个简单的例子实现注解应用
* 希望达到的效果:
* 通过传递对象的类型,获取值使用注解的值在对应表中查询数据数据满足传递过来的对象的所有条件值
*
*/
public class TestAnn {
public static void main(String[] args) {
TestAnn ta=new TestAnn();
Student s=new Student();
s.setName("郭大侠");
s.setEmail("453454@sa.com"); Student s2=new Student();
s2.setAge(21);
s2.setName("杨康"); Student s3=new Student();
s3.setEmail("1580909730@qq.com,18307006930@163.com,32919@sohu.com"); System.out.println(ta.query(s));
System.out.println(ta.query(s2));
System.out.println(ta.query(s3)); //如果需要JDBC操作,就需要将得到的使用连接池进行执行就好了
//这个代码只实现了一部分功能,仅仅是作为参考 }
public String query(Object s){//优化一下这里,传入的不一定是Student类型,为Object类型的对象
/**
* 分析:得到正确的sql语句,首先需要确定几个条件
* 这个语句时做什么的?查询
* 查询的内容是什么?*
* 查询的表名是什么?通过注解Table配置的Value值
* 查询的字段是什么?通过注解配置的Column的value
* 对应字段的值是什么?就是对应对象对应字段的值,使用getXxx()方法获取
*/
StringBuilder sb=new StringBuilder();
Class c=s.getClass();//获取字节码文件
//得到表名
String tableName=null;
Object columnName=null;
Object columnValue=null; boolean isExit=c.isAnnotationPresent(Table.class);
if(!isExit){
return null;
}
Table t=(Table) c.getAnnotation(Table.class);
tableName=t.value();
sb.append("select * from "+tableName+" where 1=1");//为什么使用1==1,为了避免后面没有条件的话报错
//接下来将@Clumn中的值和对象对应属性的值注解进去
//Field[] fileds=c.getFields();//这里注意不能直接用这个方法得到的只有public修饰的字段
Field[] fileds=c.getDeclaredFields();
for(Field f:fileds){
if(!f.isAnnotationPresent(Column.class)){
continue;
}else{
//值为null或者int类型值为0的属性不应该出来
Column cc=f.getAnnotation(Column.class);
columnName=cc.value();
//获取对应的属性
String methodName="get"+f.getName().substring(0, 1).toUpperCase()+f.getName().substring(1);
try {
columnValue= c.getMethod(methodName).invoke(s);//这里报错Integer不能转换为String
if((columnValue instanceof Integer && (Integer)columnValue==0)||columnValue==null){
continue;
}
//字符串需要加单引号
if(columnValue instanceof String){
//多个字符串字段的使用逗号拆分然后依次拼接,并且查询条件编程in,模糊查询
String[] strs=((String) columnValue).split(",");
if(strs.length>1){
sb.append(" "+columnName+" in (");
for(String ss:strs){
sb.append("'"+ss+"',");
}
sb.deleteCharAt(sb.length()-1);//减去最后一个逗号
sb.append(")");
}else{
sb.append(" and "+columnName+" = '"+columnValue+"'");
} }else{
sb.append(" and "+columnName+" = "+columnValue);
} } catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
} }
return sb.toString();
} }

java注解Annotation的更多相关文章

  1. Java - 注解 (Annotation)

    Java - 注解 (Annotation)   一.基本的 Annotation     > 使用 Annotation 时要在其前面增加 @符号,并把该 Annotation 当成一个修饰符 ...

  2. Java注解Annotation(一)

    Java注解Annotation(一)——简介 这一章首先简单介绍一下注解,下一章会给出一个注解应用的DEMO. 1. 元注解 元注解的作用是负责注解其他的注解. JDK1.5中,定义了4个标准的me ...

  3. Java注解(Annotation)详解

    转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...

  4. Java注解Annotation与自定义注解详解

    Java注解简介 开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解. 下面列举开发中常见的注解 @Override:用于标识 ...

  5. 深入JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  6. 深入学习JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  7. java注解(Annotation)解析

    注解(Annotation)在java中应用非常广泛.它既能帮助我们在编码中减少错误,(比如最常见的Override注解),还可以帮助我们减少各种xml文件的配置,比如定义AOP切面用@AspectJ ...

  8. Java注解Annotation学习

    学习注解Annotation的原理,这篇讲的不错:http://blog.csdn.net/lylwo317/article/details/52163304 先自定义一个运行时注解 @Target( ...

  9. java 注解Annotation

    什么是注解?  注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的. java注解又叫java标注,java提供了一套机制,使得我们可以对 ...

随机推荐

  1. 简单的说说jsonp

    jsonp和json有什么区别?json是一种文件格式,而jsonp是一种技术方法. jsonp会被人认为是一种新的跨域技术,其实本质上和利用带有src属性的标签进行js跨域本质没什么区别. 区别就是 ...

  2. input:text 的value 和 attribute('value') 不是一回事

    如题,input:text 当手工输入字符改变其值时,两者就不一样了. 要获得手工输入,不要用attribute('value'), 直接使用value: function getbyid(id){ ...

  3. hdu 4155 The Game of 31 博弈论

    给出序列,在剩下的卡中选择,谁先拿到大于31的输,搜一下就可以了! 代码如下: #include<cstdio> #include<cstring> ]; ],sum; boo ...

  4. Linux信号处理1

    函数原型 NAME signal - ANSI C signal handling SYNOPSIS #include <signal.h> typedef void (*sighandl ...

  5. pku 1182(种类并查集)

    题目链接:http://poj.org/problem?id=1182 解题思路来自discuss:http://poj.org/showmessage?message_id=152847 #incl ...

  6. pycharm控制台中文乱码问题

    pycharm控制台中文乱码问题一般是因为之前有配置保存到了文件里, C盘下.pycharm文件夹下有配置文件,删除文件后重装pycharm,配置会重置 不过最后解决问题的做法是删除配置文件后,重新装 ...

  7. struts2实现选择i18n语言选择切换

    [新手学习记录,仅供参考!] 1.项目准备 首先当然是我们得创建一个struts2的web项目,并且已经实现了一个简单的功能. 以下通过登录功能来举例说明. 2.指定全局国际化资源文件 在struts ...

  8. sql 泡沫 或者 递归查询

    if object_id('[tb]') is not null drop table [tb] go ),parentid int) insert [tb] ,N union all ,N unio ...

  9. 使用CSS3制作漂亮的按钮

    我给大家介绍一下如何使用CSS3来制作一个圆角阴影.渐变色的漂亮的按钮,它不需要任何图片和javascript脚本,只需要CSS3就可以轻松实现按钮效果,并且可以适用于任意HTML元素,想div,sp ...

  10. 不容错过的iOS 8的导航交互

    你曾注意过Safari移动客户端里美轮美奂的导航栏缩放效果么,以及那些tab bar是如何消失的吗? 在iOS 8中,苹果让这种类型的交互变得非常容易,虽然在WWDC上演示了缩放导航栏效果,不过后来他 ...