在慕课上学习了一个关于java注解的课程,下面是笔记以及一些源码。

Annotation——注解

1.JDK中的注解

JDK中包括下面三种注解:

@Override:标记注解(marker annotation),重写,父类写的方法,如果子类继承了父类,就要重写父类的方法。

@Deprecated:表示过时的语法加上这个注解之后,该方法上会出现一道删除线

@SuppressWarning:忽略警告,压制警告。如果某语句前面出现警告,加上这个注解,警告就会消失。

举例如下:

父类 一个Person接口: @Deprecated表示该方法过时。

package com.ann.test;

public interface Person {
public String name(); public int age(); @Deprecated
public void sing();
}

子类Child 集成父类,必须 重写@Override父类的所有方法。

package com.ann.test;

public class Child implements 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 } }

测试代码: 测试代码中调用了过时的sing()函数,产生警告。使用@SuppressWarnings注解 ,可消除警告。

package com.ann.test;

public class Test {
@SuppressWarnings("deprecation")
public void sing() {
Person p = new Child();
p.sing();
}
}

2.常见第三方注解:

Spring:

  • @Autowired:不用配置文件,可以自动生成Dao文件注入进去
  • @Serice
  • @Repository

Mybatis:

  • @InsertProvider
  • UpdataProvider
  • @Options

3.注解分类:

按照运行机制:

  • 编码注解:只存在源码中
  • 编译时注解:存在于源码与.class中 如@override、@Deprecated、@SuppressWarning
  • 运行时注解:运行时将成员变量自动注入(可能会影响运行逻辑)如Spring中的@AutoWired

按照来源:

  • JDK注解
  • 第三方注解(Spring等)
  • 自定义注解

4.自定义注解

可新建一个Annotation,@interface表示注解。在自定义注解中,

  1. 成员变量必须是无参无异常的形式,可以设置使用default设置默认值
  2. 成员变量的类型:基本数据类型、String、class、Annotation、Enumeration
  3. 成员变量只有一个的时候,一般取名为value();使用的时候,可以直接赋值
  4. 可以没有成员
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 Decription { String desc(); String author(); int age() default 18;
}
@Target:表示注解作用域,关键字包括Constructor(构造函数)、Field(变量)、Local_veriable、method、package、parameter、tyoe(类,接口)
@Retention:生命周期:source、class、runtime
@Inherited:可以被子类继承
@Documented:生成javadoc时包含注解信息 自定义注解的使用:
@<注解名>(<成员名1>=<value1>,.......)
如下:
package com.ann.test;
@Decription(desc="I am class description", author = "YM")
public class Child implements Person{ @Override
@Decription(desc="I am method description", author = "YM", age = 18)
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 }
}

5.解析注解

  1. 首先使用加载器加载类
  2. 找到类上的注解
  3. 拿到注解实例
  4. 找到方法上的注解

另一种解析方法:以方法上的注解为例

  1. 遍历所有的方法
  2. 拿出所有的注解
  3. 遍历所有注解

package com.ann.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method; public class ParseAnn {
public static void main(String[] args) {
try {
//1.使用类加载器加载类
Class c=Class.forName("com.ann.test.Child");
//2找到类上的注解
boolean isExis = c.isAnnotationPresent(Decription.class);
if(isExis){
//3.拿到注解实例
Decription d=(Decription) c.getAnnotation(Decription.class);
System.out.println(d.desc());
}
//4.找到方法上的注解
Method[] ms=c.getMethods();
for(Method m:ms){
boolean isMExis=m.isAnnotationPresent(Decription.class);
if(isMExis){
Decription mds=(Decription)m.getAnnotation(Decription.class);
System.out.println(mds.desc());
}
} //另外一种解析方法
//1.遍历所有方法
for(Method m:ms){
//2拿出所有注解
Annotation[] an=m.getAnnotations();
//3遍历所有注解
for(Annotation a:an){
//如果a是我们自定义注解的实例
if(a instanceof Decription)
{ //将a强转成Decription类
Decription d= (Decription)a;
System.out.println(d.desc());
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

输出:

I am class description
I am method description
I am method description

6.注解实战:

需求:一张用户表。自动的对每个字段或字段的组合条件进行检索,拼接sql语句,并打印

Filter.class

package com.ann.dao;

@Table("user")
public class Filter {
@Column("id")
private int id;
@Column("userName")
private String userName;
@Column("nikeName")
private String nikeName;
@Column("age")
private int age;
@Column("city")
private String city;
@Column("email")
private String email;
@Column("mobile")
private String mobile; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getNikeName() {
return nikeName;
} public void setNikeName(String nikeName) {
this.nikeName = nikeName;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getCity() {
return city;
} public void setCity(String city) {
this.city = city;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public String getMobile() {
return mobile;
} public void setMobile(String mobile) {
this.mobile = mobile;
}
}

Table (自定义注解)作用域为TYPE表示类

package com.ann.dao;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
public String value();
}

Column (自定义注解)

package com.ann.dao;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
public String value();
}

Test :

package com.ann.dao;

import java.lang.reflect.Field;
import java.lang.reflect.Method; public class Test {
// 1.首先考虑代码怎么与数据库做映射 filter是与数据库关系最紧密的类-转到filter
// 2需要考虑query方法如何实现
public static void main(String[] args) {
Filter f1 = new Filter();
f1.setId(10);// 查询id为10的用户
Filter f2 = new Filter();
f2.setUserName("Tom");// 查询用户名为tom的用户
f2.setAge(18);
Filter f3 = new Filter();
f3.setEmail("123@qq.com,haha@126.com");
String sql1 = query(f1);
String sql2 = query(f2);
String sql3 = query(f3);
System.out.println("sql1:" + sql1);
System.out.println("sql2:" + sql2);
System.out.println("sql3:" + sql3);
//写一个filter可以应用到不同的表中
Filter2 filter2= new Filter2();
filter2.setAmount(10);
filter2.setId(1);
filter2.setName("技术");
System.out.println(query(filter2));
} private static String query(Object f) {
// 首先用一个StringBuilder来存储字符串表示sql语句
StringBuilder sb = new StringBuilder();
// 1获取class
Class c = f.getClass();
// 2.获取table名
boolean isCExis = c.isAnnotationPresent(Table.class);
if (!isCExis) {
return null;
}
Table t = (Table) c.getAnnotation(Table.class);
String tableName = t.value();
sb.append("select * from ").append(tableName).append(" where 1=1");
// 3.遍历所有字段
Field[] field = c.getDeclaredFields();
for (Field fi : field) {
// 4.处理每个字段对应的sql
// 4.1拿到字段的名字
boolean isFExis = fi.isAnnotationPresent(Column.class);
if (!isFExis) {
continue;
}
Column col = fi.getAnnotation(Column.class);
String columnName = col.value();
// 4.2拿到字段的值(反射)
String fieldName = fi.getName();// 字段名
// 先拿到get方法的名字
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Object fieldValue = null;
try {
Method getMethod = c.getMethod(getMethodName);
fieldValue = getMethod.invoke(f);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 4.3拼接
if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
continue;
}
sb.append(" and ").append(fieldName);
if (fieldValue instanceof Integer) {
sb.append(" = ").append(fieldValue);
} else if (fieldValue instanceof String) {
if (((String) fieldValue).contains(",")) {// 邮箱格式包含,表示有多种选择
String[] string = ((String) fieldValue).split(",");
sb.append(" in (");
for(String str:string){
sb.append("'").append(str).append("'").append(",");
}
sb.deleteCharAt(sb.length()-1);
sb.append(")");
} else {
sb.append(" = '").append(fieldValue).append("'");
} }
}
return sb.toString();
}
}
sql1:select * from user where 1=1 and id = 10
sql2:select * from user where 1=1 and userName = 'Tom' and age = 18
sql3:select * from user where 1=1 and email in ('123@qq.com','haha@126.com')
												

【iMooc】全面解析java注解的更多相关文章

  1. 框架基础——全面解析Java注解

    为什么学习注解? 学习注解有什么好处? 学完能做什么? 答:1. 能够读懂别人写的代码,特别是框架相关的代码: 2. 让编程更加简洁,代码更加清晰: 3. 让别人高看一眼. spring.mybati ...

  2. 全面解析java注解

    一.注解概述       1.学习注解能够读懂别人的代码,特别是框架相关的代码       2.让自己的编程更加简洁,代码更加清晰       3.让别人高看一眼,会使用自定义注解来解决问题     ...

  3. 基础篇:深入解析JAVA注解机制

    目录 java实现注解的底层原理和概念 五种元注解详解 使用动态代理机制处理注解 spring.AOP和注解机制 (题外)@FunctionalInterface原理介绍 欢迎指正文中错误 关注公众号 ...

  4. 分享知识-快乐自己:全面解析 java注解实战指南

    请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...

  5. Java注解入门

    注解的分类   按运行机制分:   源码注解:只在源码中存在,编译后不存在 编译时注解:源码和编译后的class文件都存在(如@Override,@Deprecated,@SuppressWarnin ...

  6. Java注解教程:自定义注解示例,利用反射进行解析

    Java注解能够提供代码的相关信息,同时对于所注解的代码结构又没有直接影响.在这篇教程中,我们将学习Java注解,如何编写自定义注解,注解的使用,以及如何使用反射解析注解. 注解是Java 1.5引入 ...

  7. Java注解全面解析(转)

    1.基本语法 注解定义看起来很像接口的定义.事实上,与其他任何接口一样,注解也将会编译成class文件. @Target(ElementType.Method) @Retention(Retentio ...

  8. Java注解解析-搭建自己的注解处理器(CLASS注解使用篇)

    该文章是继Java注解解析-基础+运行时注解(RUNTIME)之后,使用注解处理器处理CLASS注解的文章.通过完整的Demo例子介绍整个注解处理器的搭建流程以及注意事项,你将知道如何去搭建自己的注解 ...

  9. java注解(Annotation)解析

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

随机推荐

  1. 5、JUC--实现 Callable 接口

    Callable接口  Java 5.0 在 java.util.concurrent 提供了一个新的创建执行 线程的方式:Callable 接口  Callable 接口类似于 Runnable ...

  2. /etc/hosts,GoldenGate

    [oracle@g]$ netstat -alp|grep 7809(Not all processes could be identified, non-owned process info wil ...

  3. WorldWind源码剖析系列:表面瓦片类SurfaceTile

    表面瓦片类SurfaceTile描述星球类(如地球)表面纹理影像的瓦片模型.其类图如下. 表面瓦片类SurfaceTile包含的主要的字段.属性和方法如下: int m_Level;//该瓦片所属金字 ...

  4. 将公钥部署到远程Git仓库(coding.net)

    步骤: 1.下载git通用客户端并且安装. 2.右键,在弹出的对话框中选择Git Bash 3.创建本地ssha)在弹出的终端输入ssh-keygen -t rsa -C "username ...

  5. 关于Android开发环境的演变

    是不是我天生就不适合安装软件——经过eclipse.jdk.Android Studio的历次安装,我发觉自己似乎永远都装不好.去年eclipse断断续续装了三四天,那时希望能附加C++的软件包,却始 ...

  6. 关于C#中async/await中的异常处理(上)-(转载)

    在同步编程中,一旦出现错误就会抛出异常,我们可以使用try…catch来捕捉异常,而未被捕获的异常则会不断向上传递,形成一个简单而统一的错误处理机制.不过对于异步编程来说,异常处理一直是件麻烦的事情, ...

  7. 降阶法计算行列式方法有个地方有Bug(原文也已更正,此为更正后部分)

    今天用此函数做方程求解时发现有误,特此更正: /// <summary> /// 降阶法计算行列式 /// </summary> /// <param name=&quo ...

  8. No CPU/ABI system image available for this target 解决办法

    经过了好几天的奋战,终于解决了这个问题.百度出来的方法真的是很垃圾了 最后用google,才解决出这个问题. 接下来,直入正题: 附上解决的链接:https://blog.csdn.net/doubl ...

  9. 1.5《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——清屏

    使用命令行时,使用clear命令清除屏幕非常方便: $ clear 键盘简写为^L.(Ctrl + L) 同样地,使用完终端当前窗口或标签页,使用exit命令退出进程: $ exit 键盘简写为^D ...

  10. 2017-2018-2 《网络对抗技术》 20155302 第二周 Exp1 PC平台逆向破解(5)M

    2017-2018-2 <网络对抗技术> 20155302 第二周 Exp1 PC平台逆向破解(5)M 1-实践目标 1.1-实践介绍 本次实践的对象是一个名为pwn1的linux可执行文 ...