第1章 概述
1-1 Java注解概述
为什么要学习注解?学习注解有什么好处?学完能做什么?
- 能够读懂别人的代码,特别是框架相关的代码
- 让编程更加简洁,代码更加清晰
- 让别人高看我们一眼
注解在Java1.5引入
Java提供了一种原程序中元素关联任何信息和任何元素的途径和方法
- Java中的常见注解
- 注解分类
- 自定义注解
- 注解应用实战
第2章 Java中的常见注解
2-1 JDK中的注解
JDK自带注解
- @Override
- @Deprecated
- @Suppvisewarnings
public interface Person {
public String name();
public String age();
@Deprecated
public void sing();
}
public class Child implements Person{
@Override
public String name() {
return null;
}
@Override
public String age() {
return null;
}
@Override
public void sing() {
}
}
public class Test {
@SuppressWarnings("deprecation")
public void sing() {
Person p = new Child();
p.sing();
}
}
2-2 Java第三方注解
- Spring
- @Autowired
- @Service
- @Repository
- Mybatis
- @InsertProvider
- @UpdateProvider
- @Options
第3章 注解的分类
3-1 Java注解的分类
- 按照运行机制分
- 源码注解
注解只在源码中存在,编译成.class文件就不存在了。 - 编译时注解
注解在源码和.class文件中都存在,如@Override、@Deprecated、@Suppvisewarnings - 运行时注解
在运行阶段还起作用,甚至会影响运行逻辑的注解,如@Autowired
- 源码注解
- 按照来源分类
- 来自JDK的注解
- 来自第三方的注解
- 我们自定义的注解
元注解:注解的注解
第4章 自定义注解
4-1 Java自定义注解
- 自定义注解的语法要求
- 注解的注解(元注解)
- 使用自定义注解
- 解析注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description{
String desc();
String author();
int age() default 18;
}
- 使用@interface关键字定义注解
- 成员以无参无异常方式声明
- 可以用default为成员指定一个默认值
- 成员类型是受限的,合法的类型包括基本类型以及String、Class、Annotation、Enumeration
- 如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)
- 注解类可以没有成员,没有成员的注解称为标识注解
ElementType中有:
- CONSTRUCTOR
- FIELD
- LOCAL_VARIABLE
- METHOD
- PACKAGE
- PARAMETER
- TYPE
RetentionPolicy中有:
- SOURCE
- CLASS
- RUNTIME
@Inherited:允许子类继承
@Doucument:生成javadoc时会包含注解
4-2 使用自定义注解
使用注解的语法:
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,…)
@Description(desc="I am eyeColor",author="Mooc boy",age=18)
public String eyeColor(){
return "red";
}
4-3 关于自定义注解的代码演示说明
4-4 解析注解
通过反射获取类、函数或成员上的运行时注解信息,
从而实现动态控制程序运行的逻辑。
public class ParseAnn {
public static void main(String[] args) {
try {
//1.使用类加载器加载类
Class c = Class.forName("com.ann.test.Child");
//2.找到类上面的注解
boolean isExist = c.isAnnotationPresent(Description.class);
if(isExist) {
//3.拿到注解实例
Description d = (Description)c.getAnnotation(Description.class);
System.out.println(d.value());
}
//4.找到方法上的注解
Method[] ms = c.getMethods();
for (Method m : ms) {
boolean isMExist = m.isAnnotationPresent(Description.class);
if(isMExist){
Description d = (Description)m.getAnnotation(Description.class);
System.out.println(d.value());
}
}
//另一种解析方法
for(Method m:ms) {
Annotation[] as = m.getAnnotations();
for (Annotation a : as) {
if(a instanceof Description) {
Description d = (Description)a;
System.out.println(d.value());
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description{
String value();
// String author();
// int age() default 18;
}
@Description("I am interface")
public class Person {
@Description("I am interface method")
public String name() {
return null;
};
public String age() {
return null;
};
@Deprecated
public void sing() {};
}
public class Child extends Person{
@Override
public String name() {
return null;
}
@Override
public String age() {
return null;
}
@Override
public void sing() {
}
}
第5章 项目实战
5-1 项目需求
项目说明:项目取自一个公司的持久层框架,用来代替Hibernate的
解决方案,核心代码就是通过注解来实现的。
需求:
1. 有一张用户表,字段包括用户ID,用户名,昵称,年龄,
性别,所在城市,邮箱,手机号。
2. 方便的对每个字段或字段的组合条件进行检索,并打印SQL。
3. 使用方式要足够简单,见代码示例。
5-2 项目实现(上)
5-3 项目实现(下)
public class Test {
public static void main(String[] args) {
Filter f1 = new Filter();
f1.setId(10);//查询id为10的用户
Filter f2 = new Filter();
f2.setUserName("lucy");//查询用户为lucy的用户
f2.setAge(18);
Filter f3 = new Filter();
f3.setEmail("liu@sina.com,zh@163.com,77777@qq.com");
String sql1 = query(f1);
String sql2 = query(f2);
String sql3 = query(f3);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
Filter2 filter2 = new Filter2();
filter2.setAmount(10);
filter2.setName("技术部");
System.out.println(query(filter2));
}
private static String query(Object f) {
StringBuilder sb = new StringBuilder();
//1.获取到class
Class c = f.getClass();
//2.获取到table的名字
boolean exists = c.isAnnotationPresent(Table.class);
if(!exists) {
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[] fArray = c.getDeclaredFields();
for (Field field : fArray) {
//4.处理每个字段对应的sql
//4.1拿到字段名
boolean fExists = field.isAnnotationPresent(Column.class);
if(!fExists) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//4.2拿到字段的值
String filedName = field.getName();
String getMethodName = "get"+ filedName.substring(0,1).toUpperCase() +
filedName.substring(1);
Object fieldValue = null;
try {
Method getMethod = c.getMethod(getMethodName);
fieldValue =getMethod.invoke(f, null);
} catch (Exception e) {
e.printStackTrace();
}
//4.3拼装sql
if(fieldValue == null ||
(fieldValue instanceof Integer && (Integer)fieldValue == 0)) {
continue;
}
sb.append(" and ").append(filedName);
if(fieldValue instanceof String) {
if(((String)fieldValue).contains(",")) {
String[] values = ((String)fieldValue).split(",");
sb.append(" in(");
for (String v : values) {
sb.append("'").append(v).append("'").append(",");
}
sb.deleteCharAt(sb.length()-1);
sb.append(")");
}else {
sb.append("=").append("'").append(filedName).append("'");
}
}else if(fieldValue instanceof Integer) {
sb.append("=").append(fieldValue);
}
}
return sb.toString();
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
@Table("user")
public class Filter {
@Column("id")
private int id;
@Column("user_name")
private String userName;
@Column("nick_name")
private String nickName;
@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 getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
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("department")
public class Filter2 {
@Column("id")
private int id;
@Column("name")
private String name;
@Column("leader")
private String leader;
@Column("amount")
private int amount;
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 String getLeader() {
return leader;
}
public void setLeader(String leader) {
this.leader = leader;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
第6章 课程总结
6-1 课程总结
- 认识注解
- 注解作用范围@Target和生命周期@Retention
- 作用范围:包、类、字段、方法的参数、局部变量
- 生命周期:源文件SOURCE、编译CLASS、运行RUNTIME
- 能读懂注解