Java注解简介、自定义注解及模拟Junit、模拟hibernate根据实体类建表

注解简介

注解:JDK1.5的新特性

注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。

Java SE5 三个内置标准注解

  • @Override:方法覆盖、重写;
  • @Deprecated:过时的;
  • @SupperessWornings:关闭不当的编译器警告信息;

元注解:

  • @Target:表示注解在什么地方使用,可用ElementType,其值为:
    * constructor:说明该方法用在构造方法上;
    * field:说明盖注解用在属性上;
    * local_variable:局部变量上;
    * method:用在方法上;
    * package:用在包声明上;
    * parameter:用在参数上;
    * type:用在类或接口上;

  • @Retention:表示需要在什么级别保存该注解信息,可能的参数值RetentionPolicy为:
    source:表示该注解会被编译器丢弃
    class:说明该注解会在.class文件中,但会被JVM丢弃
    runtime:jvm将在运行期间保留,因此可以通过反射机制来读取注解信息

  • @Documented:将该注解包含在JavaDoc中。表示此注解会被javadoc工具提取成文档。

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

自定义注解

  1. 定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)		//说明此注解用在方法上
@Retention(RetentionPolicy.RUNTIME)		//说明是运行级别
public @interface Info {
	int id();			//为区分接口与类,在后面加上()
	String des() default "暂无信息";
}
  1. 定义目标类
public class TestInfo {
	@Info(id=1,des="show方法")
	public void show() {
		System.out.println("阴雨绵绵。。。");
	}
	@Info(id=2)
	public String getInfo() {
		return "欸。。。";
	}
	public void description(){
		System.out.println("真是应景。。。");
	}
}
  1. 定义测试类
public class InfoTracker {
	public static void main(String[] args) {
		test(TestInfo.class);
	}
	public static void test(Class<TestInfo> cl) {
		Info info = null;
		for( Method method : cl.getDeclaredMethods() ){	//循环给定类中的所有方法。也可以给定包路径,自动扫描该包下的所有类
			if( method.isAnnotationPresent( Info.class ) ){
				//method.getAnnotations();	//获取这个方法上的所有注解
				
				//现在我们只想知道是否有我们给定的注解Info
				System.out.println( method.getName() + "有Info注解" );
				
				info = method.getAnnotation(Info.class);
				System.out.println(info.id() + "-" + info.des());
			}else{
				System.err.println( method.getName() + "没有Info注解" );
			}
		}
	}
}

Java注解模拟实现Junit

  1. 创建注解类
import java.lang.annotation.*;

@Target(value={ElementType.METHOD})		//目标:作用域方法		//两种写法
@Retention(RetentionPolicy.RUNTIME)		//保留范围:运行时保留,不会被jvm丢弃
public @interface Beta {
	//这个注解类中不需要任何属性
}
  1. 编写测试用例类
public class Test {
	@Beta	//加上自定义的测试注解
	public void test(){
		System.out.println("SUCCESS!");
	}
	@Beta
	public void test2(){
		System.out.println("成功了!哈哈哈...");
	}
	@Beta
	public void test3(){
		System.err.println("嘻嘻嘻...");
	}
}
  1. 编写注解方法的操作测试类
public class TestBeta {
	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		Class clazz = Test.class;
		
		Method[] methods = clazz.getMethods();
		if(methods != null){
			for(Method method : methods){
				boolean isAP = method.isAnnotationPresent(Beta.class);
				if(isAP){
					method.invoke(clazz.newInstance(), null);
				}
			}
		}
	}
}

注解模拟Hibernate中根据实体类在数据库建表的方法

  1. 创建用来指定表名的注解
import java.lang.annotation.*;
@Target(ElementType.TYPE)		//说明作用在类上
@Retention(RetentionPolicy.RUNTIME)	//运行时级别
public @interface TableName {
	public String name() default "";
}
  1. 创建用来指定类型的注解
import java.lang.annotation.*;
@Target(ElementType.FIELD)		//说明用在属性上
@Retention(RetentionPolicy.RUNTIME)
public @interface Type {
	public String type() default "varchar(20)";
	public Constraints constraints() default @Constraints;
}
  1. 创建指定约束的注解
@Target(ElementType.FIELD)		//说明在属性上
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
	public boolean primaryKey() default false;	//是否为主键
	public boolean allowNull() default true;	//是否可为空
	public boolean unique() default false;		//是否唯一
	public boolean identity() default false;	//是否自增
}
  1. 创建实体类
@TableName
public class StuInfo {
	@Type(type="int" ,constraints=@Constraints(primaryKey=true,identity=true))
	private int usid;
	
	@Type(type="varchar(200)" ,constraints=@Constraints(allowNull=false,unique=true))
	private String sname;
	
	@Type(type="int")
	private int age;
	
	@Type(constraints=@Constraints(unique=true))
	private String tel;
	public int getUsid() {
		return usid;
	}
	public void setUsid(int usid) {
		this.usid = usid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
}
  1. 创建测试类
public class TableCreator {
	public static void main(String[] args) {
		TableCreator tc = new TableCreator();
		tc.run();
	}
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public void run(){
		Connection con = null;
		Statement stmt = null;
		try {
			con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","数据库用户名","密码");
			stmt = con.createStatement();
			String sql = this.getSql(StuInfo.class);
			System.out.println(sql);
			stmt.execute(sql);	//执行sql
			System.out.println("创建成功");
		} catch (Exception e) {
			System.err.println("创建失败");
			e.printStackTrace();
		}finally {
			try {
				if(stmt != null){
					stmt.close();
				}
				if( con != null ){
					con.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	//建表语句
	public String getSql(Class<?> cl){
		TableName tn = cl.getAnnotation(TableName.class);
		if(tn == null){
			return null;
		}
		String tableName = tn.name();
		if( tableName == null || "".equals(tableName) ){
			tableName = cl.getSimpleName();	//这里不要使用getName(),那样会返回带有包路径的字符串值
		}
		//如果需要考虑性能,建议使用StringBuffer
		StringBuffer sbf = new StringBuffer();
		sbf.append("create table ").append(tableName).append("(");
		//拼接列  ->  获取这个对象中的所有属性  ->  判断属性上是否有Type注解
		Field[] fields = cl.getDeclaredFields();
		if(fields == null || fields.length <= 0){
			return null;
		}
		Type type = null;
		for( Field field : fields ){
			type = field.getAnnotation(Type.class);
			if(type != null){
				sbf.append( field.getName() ).append(" ").append( type.type() );
				//这个列上的约束
				if( type.constraints().primaryKey() ){	//如果是主键
					sbf.append(" primary key");
					if( type.constraints().identity() ){//则需要判断是否自增
						sbf.append(" auto_increment");
					}
				}else{//不是主键,判断是否可为空,是否唯一
					if( !type.constraints().allowNull() ){	//不可为空
						sbf.append(" not null");
					}
					if( type.constraints().unique() ){	//唯一
						sbf.append(" unique");
					}
				}
				sbf.append(",");
			}
		}
		String sql = sbf.toString();
		//处理最后一个多余的逗号,并加上反括号
		sql = sql.substring(0,sql.lastIndexOf(",")) + ")";
		return sql;
	}
}
发布了40 篇原创文章 · 获赞 16 · 访问量 8632

猜你喜欢

转载自blog.csdn.net/qq_40366738/article/details/104573771