扯扯注解的蛋

为什么学习注解?学习注解有什么好处?学完能做什么?
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. vi/vim使用指北 ---- Moving Around in a Hurry

    上一篇文章中,简单列出了一些基本的Vim操作,也列出了很多的光标移动命令,本章主要是有哪些命令可以更快的移动光标. vim的编辑操作,用得最多就是移动光标,对于很少行的文件来说,基本的命令就够用了,但 ...

  2. HDU4945 2048(dp)

    先是看错题意..然后知道题意之后写了发dp..无限TLE..实在是不知道怎么优化了,跑了遍数据是对的,就当作理论AC掉好了.. #pragma warning(disable:4996) #inclu ...

  3. 【转】dip,px,pt,sp 的区别

    dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不依赖像素. ...

  4. ExtJs之Ext.getCmp

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  5. zoj 3529 A Game Between Alice and Bob 博弈论

    思路:每个数的SG值就是其质因子个数,在进行nim博弈 代码如下: #include<iostream> #include<cstdio> #include<cmath& ...

  6. JAVA IO 体系

    一.体系结构

  7. 安装 M2eclipse 插件

    安装 M2eclipse 插件 在 Eclipse 中集成 Maven 插件能极大的方便创建 Maven project 并对其进行操作.使用以下的步骤来完成 M2eclipse 插件的安装: 在 E ...

  8. @RequestBody 的正确使用办法

    1.以前一直以为在SpringMVC环境中,@RequestBody接收的是一个Json对象,一直在调试代码都没有成功,后来发现,其实 @RequestBody接收的是一个Json对象的字符串,而不是 ...

  9. 怎样在java代码中调用执行shell脚本

    // 用法:Runtime.getRuntime().exec("命令"); String shpath="/test/test.sh"; //程序路径 Pro ...

  10. 让浏览器屏蔽js

    有时候为了测试js是否做到了渐进增强,需要屏蔽下js 做法: Internet选项>>安全>>自定义级别 禁用java小程序脚本和活动脚本 有的浏览器调试器直接就有这个功能