Java注解

本篇文章主要是作者学习注解的一些记录,希望能帮到您,如果有什么不妥当的地方希望得到指出,谢谢阅读
Java学习大纲:https://blog.csdn.net/weixin_39778570/article/details/94667501
JavaWeb:https://blog.csdn.net/weixin_39778570/article/details/97800485

理解

下面这张图总结的挺好的,一开始开不太懂,可以看完后回顾一下
在这里插入图片描述
在定义注解的时候我们需要对我们的注解进行一些定义,也就是元注解,可以认为是注解的注解,主要的功能是给我们的注解生成一些标签,告诉编译器我们的注解应用于怎么样的场景。
而实现这些功能的东西你可以大概地称它为元标签,目前有下面几种元标签:
元注解是java API提供,是专门用来定义注解的注解,其作用分别如下:
@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 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。
相当与@see,@param 等。

@Inherited 允许子类继承父类中的注解。

Java本身提供的注解

JDK1.5之后内部提供的三个注解

   @Deprecated 意思是“废弃的,过时的”

   @Override 意思是“重写、覆盖”

   @SuppressWarnings 意思是“压缩警告”

简单例子

我们在书写我们的注解的时候,理所当然应该写一个解释器,比如解释我们注解的类,不然我们的注解就没有发生作用了
在这里插入图片描述
编写一个简单的注解,注意:注解必须有值,所以一般default一个默认值

package myannotations.first;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 定义一个注解
 * 描述包含id和description,最好有默认值default
 * 注解元素:
 * 	基本类型
 *  String
 *  Class
 *  Enum
 *  Annotation
 * @author Administrator
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
	public int id(); // 这里不设置默认值进行测试,编译器要求使用注解的时候必须有一个值不能为null
	public String description() default "not description";
}

使用注解

package myannotations.first;

import java.util.List;
/**
 * 使用UseCase注解
 * @author Administrator
 *
 */
public class PasswordUtils {
	@UseCase(id = 47, description = "Passwords must contain at least one numeric")
	public boolean validatePassword(String password) {
		return (password.matches("\\w*\\d\\w*"));
	}
	
	@UseCase(id = 48) // 这里必须给id赋值
	public String encryptPassword(String password) {
		return new StringBuilder(password).reverse().toString();
	}
	
	@UseCase(id = 49, description="New passwords can't equal previously used ones")
	public boolean checkForNewPassword(List<String> prevPasswords, String password) {
		return !prevPasswords.contains(password);
	}
}

注解解释器

package myannotations.first;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 注解解释器
 * @author Administrator
 *
 */
public class UseCaseTracker {
	public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
		for(Method m : cl.getDeclaredMethods()) { // 读取类的方法
			UseCase uc = m.getAnnotation(UseCase.class); // 读取方法的注解
			if(uc != null) {
				System.out.println("Found Use Case:" + uc.id() + " "
						+ uc.description());	
				useCases.remove(new Integer(uc.id()));
			}
		}
		for(int i : useCases) {
			System.out.println("Warning Missing use case-" + i);
		}
	}
	
	public static void main(String[] args) {
		List<Integer> useCases = new ArrayList<Integer>();
		Collections.addAll(useCases, 47,48,49,59);
		trackUseCases(useCases, PasswordUtils.class);
	}
}

实验结果
在这里插入图片描述

实现SQL语句的自动生成

我们在使用一些数据库框架的使用,我们不需要写SQL语句就能实现表的创建,这里我们也简单实现(当然框架里不会这么简单…)一下表的SQL语句的生成,当然你如果连接上了数据库,自然也可以自动生成表了,这里就没有实现对数据库的连接了
在这里插入图片描述
表的注解

package myannotations.second;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 数据库表注解
 * @author Administrator
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
	public String name() default "";
}

约束的注解

package myannotations.second;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

/**
 * 列约束
 * @author Administrator
 *
 */

@Target(ElementType.FIELD)
public @interface Constrains {
	boolean primaryKey() default false;
	boolean allowNull() default true;
	boolean unique() default false;
}

Data类型的注解

package myannotations.second;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 列:Date
 * @author Administrator
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLDate {
	String name() default "";
	Constrains constrains() default @Constrains;
}

整形类型的注解

package myannotations.second;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 列:整形
 * @author Administrator
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
	String name() default "";
	Constrains constrains() default @Constrains;
}

字符串类型的注解

package myannotations.second;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 列:字符串
 * @author Administrator
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
	int value() default 0; // 若使用注解的使用,只使用一个注解元素,默认使用value
	String name() default "";
	Constrains constrains() default @Constrains;
}

表的主键的注解

package myannotations.second;

/**
 * 定义主键
 * @author Administrator
 *
 */
public @interface Uniqueness {
	Constrains constrains() default @Constrains(unique=true);
}

定义一张表,由它作为原型POJO对象生成我们的表SQL语句

package myannotations.second;

import java.util.Date;

/**
 * 定义一个Bean,为表原型
 * @author Administrator
 *
 */

@DBTable(name = "t_member")
public class Member {
	@SQLInteger(constrains = @Constrains(primaryKey = true, allowNull=false))
	Integer id;
	
	@SQLInteger
	Integer age;
	
	@SQLString(30)
	String firstName;
	
	@SQLString(value=50)
	String lastName;
	
	@SQLDate(name="birthday")	
	Date birthday;
	/* getter和setter */
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

注解解释器

package myannotations.second;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class TableCreator {
	public static void create(String[] classNames) throws ClassNotFoundException {
		if(classNames.length < 1) {
			System.out.println("没有要创建的表");
			return;
		}
		// 枚举要创建的表
		for(String className : classNames) {
			// 获取原型类
			Class<?> cl = Class.forName(className);
			DBTable dbTable = cl.getAnnotation(DBTable.class);
			if(dbTable == null) {
				continue;
			}
			String tableName = dbTable.name();
			// 如果没有定义表名,默认使用类名小写(当然,一般是驼峰改下划线)
			if(tableName.length() < 1) {
				tableName = cl.getName().toLowerCase();
			}
			
			// 列名
			List<String> columnDefs = new ArrayList<String>();
			for(Field field : cl.getDeclaredFields()) {
				String columnName = null;
				// 获取一个方法的所有注解
				Annotation[] anns = field.getDeclaredAnnotations();
				if(anns.length < 1) {
					continue; // 没有列名
				}
				// 处理被SQLInteger修饰的注释
				if(anns[0] instanceof SQLInteger) {
					SQLInteger sInt = (SQLInteger) anns[0];
					// 没有设置列名,按照属性名小写命名
					if(sInt.name().length() < 1) {
						columnName = field.getName().toLowerCase();
					}else {
						columnName = sInt.name();
					}
					columnDefs.add("`" + columnName + "` INT" 
							+ getConstrains(sInt.constrains()));
				}
				// 处理被SQLString修饰的注释
				if(anns[0] instanceof SQLString) {
					SQLString sString = (SQLString)anns[0];
					// 没有设置列名,按照属性名小写命名
					if(sString.name().length() < 1) {
						columnName = field.getName().toLowerCase();
					}else {
						columnName = sString.name();
					}
					columnDefs.add("`" + columnName + "` VARCHAR(" + sString.value() + ")"
							+ getConstrains(sString.constrains()));
				}
				// 处理被SQLDate修饰的注释
				if(anns[0] instanceof SQLDate) {
					SQLDate sDate = (SQLDate)anns[0];
					// 没有设置列名,按照属性名小写命名
					if(sDate.name().length() < 1) {
						columnName = field.getName().toLowerCase();
					}else {
						columnName = sDate.name();
					}
					columnDefs.add("`" + columnName + "` Date"
							+ getConstrains(sDate.constrains()));
				}
			}
			// 生成完整的创建表的SQL语句
			StringBuilder createCommand = new StringBuilder("CREATE TABLE `" + tableName + "` (");
			for(String columnDef : columnDefs) {
				createCommand.append("\n    " + columnDef + ",");
			}
			String tableCreate = createCommand.substring(0, createCommand.length()-1) + ");";
			System.out.println("Table Creation SQL for " + className + " is:\n" 
					+ tableCreate + "\n");
		}
	}
	// 约束处理
	private static String getConstrains(Constrains con) {
		String constrains = "";
		if(!con.allowNull()) {
			constrains += " NOT NULL";
		}
		if(con.primaryKey()) {
			constrains += " PRIMARY KEY";
		}
		if(con.unique()) {
			constrains += " UNIQUE";
		}
		return constrains;
	}
	public static void main(String[] args) throws ClassNotFoundException {
		String[] classNames = new String[]{"myannotations.second.Member"};
		create(classNames);
	}
}

实验结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值