简单介绍Java的反射原理
Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。Java程序要能够运行,java虚拟机需要事先加载java类,目前我们的程序在编译期就已经确定哪些java类需要被加载。
Java的反射机制是在编译时并不确定哪个类需要被加载,而是在程序运行时才加载、探知、自审。这样的特点就是反射。
何为自审:通过Java的反射机制能够探知到java类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。
Java的反射原理最典型的应用就是各种Java IDE:比如Jcreator,eclipse,idea等,当我们构建出一个对象时,去调用该对象的方法和属性的时候。一按点,IDE工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供我们进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审的过程。
直接上代码。
主方法类
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.Date;
import com.soa.mdm.exception.CustomException;
import com.soa.mdm.util.DateUtil;
import com.soa.mdm.util.DbUtil;
import com.soa.mdm.util.GetEntityPathUtil;
import com.soa.mdm.util.PropertiesUtil;
import com.soa.mdm.util.StringUtil;
import com.soa.mdm.util.tableNameUtil;
/**
* 如何在SpringMVC框架中利用Java反射机制和Javassist实现Java对象、属性、注解的动态创建生成
*
* @author Mr.z
* @createTime 2016年12月23日-下午3:54:47
* @version 1.0.0
*/
public class DynamicCreateObjectFromDatabase {
private String packageOutPath = "com.soa.mdm.entity";// 指定实体生成所在包的路径
private String[] colNames; // 列名数组
private String[] colTypes; // 列名类型数组
private int[] colSizes; // 列名大小数组
private boolean isImportUtil = false; // 是否需要导入包java.util.*
private boolean isImportSql = false; // 是否需要导入包java.sql.*
private String tableName = ""; // 数据库表名称
private String entityTableName = ""; // 实体表名称
private String primaryKeyName = ""; // 表主键
private String authorName = "Mr.Z";
public static void main(String[] args) throws Exception {
DynamicCreateObjectFromDatabase dcofd = new DynamicCreateObjectFromDatabase();
dcofd.GenEntityOracle("code_rules");//code_rules为数据库中的表名
}
/**
* 生成oracle表实体
*
* @author Mr.Z
* @throws Exception
* @Time 2016年12月22日 下午3:57:30
*/
public void GenEntityOracle(String tablename) throws Exception {
this.tableName = tablename;
entityTableName = tableNameUtil.initTableName(tablename);
String schema = tableNameUtil.upperCaseTableName(PropertiesUtil.getValue("jdbc.username"));
Connection con = null;
String sql = "select * from " + tablename;
con = DbUtil.getCon();
DatabaseMetaData databaseMetaData = con.getMetaData();
ResultSet rsPriKeys = databaseMetaData.getPrimaryKeys(null, schema,
tableNameUtil.upperCaseTableName(tablename));
if (rsPriKeys.getFetchSize() < 1) {
throw new CustomException("表或视图不存在!");
}
if (rsPriKeys.next()) {
if (StringUtil.isEmpty(rsPriKeys.getString(4))) {
throw new CustomException("表主键不能为空!");
}
primaryKeyName = rsPriKeys.getString(4);
}
Statement pstmt = con.createStatement();
ResultSet rs = pstmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
int size = rsmd.getColumnCount();
System.out.println(size);
colNames = new String[size];
colTypes = new String[size];
colSizes = new int[size];
for (int i = 0; i < size; i++) {
colNames[i] = rsmd.getColumnName(i + 1); // 获取列命
colTypes[i] = rsmd.getColumnTypeName(i + 1); // 获取列类型
if (colTypes[i].equalsIgnoreCase("date") || colTypes[i].equalsIgnoreCase("timestamp")) {
isImportUtil = true;
}
if (colTypes[i].equalsIgnoreCase("blob") || colTypes[i].equalsIgnoreCase("char")) {
isImportSql = true;
}
colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
}
String content = parse(colNames, colTypes, colSizes);
// File directory = new File("");
// System.out.println("绝对路径:"+directory.getAbsolutePath());
// System.out.println("相对路径:"+directory.getCanonicalPath());
String outputPath = GetEntityPathUtil.getEntityPath(entityTableName);
/*
* outputPath =
* "E:\\workspace\\Mdm\\src\\main\\java\\com\\soa\\mdm\\entity\\" + initcap(tablename) + "
* .java";
*/
FileWriter fw = new FileWriter(outputPath);
PrintWriter pw = new PrintWriter(fw);
pw.println(content);
pw.flush();
pw.close();
DbUtil.closeCon(con);
}
/**
* 功能:生成实体类主体代码
*
* @param colNames
* 列名数组
* @param colTypes
* 列名类型数组
* @param colSizes
* 列名大小数组
* @return
*/
private String parse(String[] colNames, String[] colTypes, int[] colSizes) {
StringBuffer sb = new StringBuffer();
sb.append("package " + this.packageOutPath + ";\r\n\r\n");
// 判断是否导入工具包
if (isImportUtil) {
sb.append("import java.util.Date;\r\n\r\n");
}
if (isImportSql) {
sb.append("import java.sql.*;\r\n\r\n");
}
sb.append("import javax.persistence.Entity;\r\n");
sb.append("import javax.persistence.GeneratedValue;\r\n");
sb.append("import javax.persistence.Id;\r\n");
sb.append("import javax.persistence.Table;\r\n\r\n");
sb.append("import org.hibernate.annotations.GenericGenerator;\r\n");
sb.append("\r\n");
// 注释部分
sb.append("/**\r\n");
sb.append("* @author cc\r\n");
sb.append("* " + entityTableName + " 实体类\r\n");
sb.append("* @version 1.0.0\r\n");
sb.append("* @date" + DateUtil.formatDate(new Date(), "yyyy年MM月dd日") + " " + this.authorName + "\r\n");
sb.append("* @company china-sa\r\n");
sb.append("*/ \r\n");
// Hibernate注解部分
sb.append("@Entity\r\n");
sb.append("@Table(name = \"" + tableName + "\")\r\n");
// 实体部分
sb.append("public class " + tableNameUtil.initTableName(entityTableName) + "{\r\n\r\n");
processAllAttrs(sb);// 属性
sb.append("\r\n");
processAllMethod(sb);// get set方法
sb.append("}\r\n\r\n");
return sb.toString();
}
/*
* 功能:生成所有属性
*
* @param sb
*/
private void processAllAttrs(StringBuffer sb) {
for (int i = 0; i < colNames.length; i++) {
sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + colNames[i] + ";\r\n");
}
}
/**
* 功能:生成所有方法
*
* @param sb
*/
private void processAllMethod(StringBuffer sb) {
for (int i = 0; i < colNames.length; i++) {
if (primaryKeyName.equals(colNames[i])) {
sb.append("\t@Id\r\n\t");
sb.append("@GeneratedValue(generator = \"system-uuid\")\r\n\t");
sb.append("@GenericGenerator(name = \"system-uuid\", strategy = \"uuid\")\r\n");
}
sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + tableNameUtil.initTableName(colNames[i])
+ "(){\r\n");
sb.append("\t\treturn " + colNames[i] + ";\r\n");
sb.append("\t}\r\n\r\n");
sb.append("\tpublic void set" + tableNameUtil.initTableName(colNames[i]) + "("
+ sqlType2JavaType(colTypes[i]) + " " + colNames[i] + "){\r\n");
sb.append("\t\t this." + colNames[i] + "=" + colNames[i] + ";\r\n");
sb.append("\t}\r\n\r\n");
}
}
/**
* 功能:获得列的数据类型
*
* @param sqlType
* @return
*/
private String sqlType2JavaType(String sqlType) {
if (sqlType.equalsIgnoreCase("binary_double")) {
return "double";
} else if (sqlType.equalsIgnoreCase("binary_float")) {
return "float";
} else if (sqlType.equalsIgnoreCase("blob")) {
return "byte[]";
} else if (sqlType.equalsIgnoreCase("blob")) {
return "byte[]";
} else if (sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("nvarchar2")
|| sqlType.equalsIgnoreCase("varchar2")) {
return "String";
} else if (sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("timestamp")
|| sqlType.equalsIgnoreCase("timestamp with local time zone")
|| sqlType.equalsIgnoreCase("timestamp with time zone")) {
return "Date";
} else if (sqlType.equalsIgnoreCase("number")) {
return "Integer";
}
return "String";
}
}
工具类:
一
import java.io.File;
/**
* 获取路径
*
* @author cc
* @createTime 2016年12月22日-下午4:48:06
* @version 1.0.0
*/
public class GetEntityPathUtil {
public static String getEntityPath(String tableName) throws Exception {
File directory = new File("");
String packageOutPath = "com\\soa\\mdm\\entity";// 指定实体生成所在包的路径
System.out.println("绝对路径:" + directory.getAbsolutePath());
/* System.out.println("相对路径:" + directory.getCanonicalPath()); */
String outputPath = directory.getAbsolutePath() + "\\src\\main\\java\\" + packageOutPath + "\\" + tableName
+ ".java";
return outputPath;
}
二
public class tableNameUtil {
public static void main(String[] args) {
// 将表名去掉下划线转化为峰驼式
String tableName = tableNameUtil.initTableName("code_rules");
System.out.println(tableName);
// 将表名全部转化为大写
String upperCasetableName = tableNameUtil.upperCaseTableName("code_rules");
}
/**
* 功能:将表名转化为实体名称,以下划线分割 如:code_rules => CodeRules
*
* @param str
* @return
*/
public static String initTableName(String str) {
StringBuffer resultStr = new StringBuffer();
String[] strArr = str.split("_");
for (String s : strArr) {
char[] ch = s.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
resultStr.append(new String(ch));
}
return resultStr.toString();
}
/**
* 功能:将表名转化大写 如:code_rules => CODE_RULES
*
* @param str
* @return
*/
public static String upperCaseTableName(String str) {
char[] ch = str.toCharArray();
StringBuilder sb = new StringBuilder();
for (char c : ch) {
if (c >= 'a' && c <= 'z') {
c = (char) (c - 32);
}
sb.append(c);
}
return sb.toString();
}
}
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 读取配置文件
*
* @author
*
*/
public class PropertiesUtil {
public static void main(String[] args) {
System.out.println(PropertiesUtil.getValue("jdbc.password"));
}
/**
* 读取配置文件
*
* @param key
* @return value
*/
public static String getValue(String key) {
Properties prop = new Properties();
InputStream in = new PropertiesUtil().getClass().getResourceAsStream("/jdbc.properties");
try {
prop.load(in);
} catch (IOException e) {
e.printStackTrace();
}
return prop.getProperty(key);
}
}
部分工具包没贴出来,比如日期转字符串、JDBC连接数据库等
**效果图:**
![此图为生成的注释、注解等信息](https://img-blog.csdn.net/20161223133528465?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjc5NTQ5NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![此图为生成的注释、注解等信息](https://img-blog.csdn.net/20161223133542356?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjc5NTQ5NDk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)