Reflection学习笔记(简单的ORM映射框架)

 
Reflection
类加载器 (classloader) ——用来加载 .class 文件
bootstrap( 引导指令 )— 能加载所有加载器,但他不能被任何人所加载,我们永远拿不到它,他是万物之母。 Jdk/jre./lib/rt.jar
 
Extclassloader( 可扩展的类加载器 )— 他被 bootstrap 所加载,他能加载 jdk/jre/lib/ext 目录下的所有 .jar 文件的类 .(jar 命令打包 )
 
Appclassloader(classpath 类加载器 ) ——被 Extclassloader 所加载,平时用得最多的也就是他。
 
自定义类加载器 ( 扩展某个类加载器 ) ——注意一下,自定义的类加载器是被 classpath 类加载器所加载的。搜索 jdk 目录 classloader 有关的文件 , 可以看到许多类加载器的 java 文件,选择 URLClassLoader 扩展 . 代码见 (Demo), 可以看到把类文件放到我们自定义类加载器的目录下面,即可以被加载了!
要点:静态成员在同一个线程被同一个类加载器加载的情况下只有一个副本,但是被多个线程或多个类加载器加载的情况下就有多个副本。这就关系到一个隔离性的问题, JDK 为了防止这种现象发生,不同的线程多个类加载器加载的类的对象之间不能够相互访问!
一个类加载器实例:
import  java.net. * ;
import  java.io. * ;
public   class  MyClassLoader  extends  URLClassLoader {
    
private static File file=new File("e:/temp/");
    
public MyClassLoader(){
        
super(getURL());
    }

    
public static URL[] getURL(){
        URL[] url
=null;
        
try{
            url
=new URL[]{file.toURL()};
        }
catch(Exception e){
            e.printStackTrace();
        }

        
return url;
    }

    
}
 
List<String> ——这是指泛型集合对象。
 
JAVA 共享的静态块中到底有什么?有除了具体的非静态成员的值以外的所有,包括非静态成员方法,属性,静态方法,属性 , 类的实例 …..
六种获得类对象的方法 :
1.        From getClass().
                         i.              String str = "abc";
                       ii.              Class c1 = str.getClass();
 
2.        From the method Class.getSuperclass()
                         i.              Button b = new Button();
                       ii.              Class c1 = b.getClass();
                      iii.              Class c2 = c1.getSuperclass();
BTW getSuperclass() returns null for the class Object.
 
3.        From the static method Class.forName() ——运行时加载类对象
      Class c1 = Class.forName ("java.lang.String");
      Class c2 = Class.forName ("java.awt.Button");
      Class c3 = Class.forName
                                             ("java.util.LinkedList$Entry");
      Class c4 = Class.forName ("I");
      Class c5 = Class.forName ("[I");
 
 
4.        From the .class syntax 类的构造
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
 
5.        From the primitive wrapper classes 原始类型的包装类
      Class c1 = Boolean.TYPE;
      Class c2 = Byte.TYPE;
      Class c3 = Character.TYPE;
      Class c4 = Short.TYPE;
      Class c5 = Integer.TYPE;
      Class c6 = Long.TYPE;
      Class c7 = Float.TYPE;
      Class c8 = Double.TYPE;
      Class c9 = Void.TYPE;
 
6 .通过类加载器直接加载 .class 文件获得类对象 .
 
要点:如果要取得一个属性的值,必须给定一个对象,因为在静态块中他并不知道这个属性到底属于哪个具体的类对象: Width.set(r,newWidth) 其中 r 就是具体的类对象, newWidth 为新值。
 
Method m=b.getClass().getMethod(“f”,null) 其中 null 参数可以传一个参数数组
Class[] args=new Class[]{int.class,int.class} ——这里指一个类对象类型的参数数组 .
 
JAVA 创建类对象的方式:
1. New 对象
2. 反射
3. Clone
其中前两种要加构造函数。

 下面就动手来做一个简单的ORM框架:

这是一个bean的XML配置文件:

<? xml version="1.0" encoding="UTF-8" ?>
< xml-body >
    
< bean  id ="item1"  class ="test.Item"  table ="Item" >
        
< properties  name ="id"  type ="Integer" />
        
< properties  name ="name"  type ="String" />
        
< properties  name ="description"  type ="String" />
        
< properties  name ="price"  type ="Double" />
    
</ bean >
    
< sql  id ="selAll"  table ="Item" > select * from Item </ sql >
</ xml-body >

下面是建表语句:

CREATE   TABLE  ITEM
(
    ID 
INT   PRIMARY   KEY   IDENTITY ( 0 , 1 ),
    NAME 
VARCHAR ( 20 ),
    DESCRIPTION 
VARCHAR ( 50 ),
    PRICE 
MONEY
)

想一下,用户在上面XML配置文件中配置了一个SQL语句,那么他只要传一个ID就可以通过配置文件里面的SQL语句返回一个Bean的集合。具体实现如下:注释我都写在代码中了,自己看吧.

 

 

 

package  test;

import  java.io.File;
import  java.util.ArrayList;
import  java.util.Iterator;
import  java.util.List;

import  org.dom4j.Document;
import  org.dom4j.DocumentException;
import  org.dom4j.Element;
import  org.dom4j.io.SAXReader;

public   class  XMLParse  {
    
private String tablename;
    
private String beanname;
    
private List attrList=new ArrayList();
    
private int count=0;
    
public String getTablename() {
        
return tablename;
    }



    
public void setTablename(String tablename) {
        
this.tablename = tablename;
    }


//读配置文件<sql>获得sql语句,表名
    public String getSql(String sqlId){
        SAXReader sax
=new SAXReader();
        Document doc
=null;
        String strSql
=null;
        
try {
            doc 
= sax.read(new File("test/item.xml"));
            Element root
=doc.getRootElement();
            
for (Iterator iter = root.elementIterator(); iter.hasNext();) {
                Element element 
= (Element) iter.next();
                
if(element.getName().equalsIgnoreCase("sql"&& element.attributeValue("id").equalsIgnoreCase(sqlId)){
                    strSql
=element.getStringValue();
                    tablename
=element.attributeValue("table");
                    
break;
                }

                
            }

        }
 catch (DocumentException e) {
            
// TODO 自动生成 catch 块
            e.printStackTrace();
        }

        
return strSql;
    }

    
    
    
    
public static void main(String[] args) {
//        System.out.println(XMLParse.getSql("selAll"));
    }


//根据表名读配置文件获得bean的名字
    public String getBeanname(String tablename) {
        SAXReader sax
=new SAXReader();
        Document doc
=null;
        String beanname
=null;
        
try {
            doc 
= sax.read(new File("test/item.xml"));
            Element root
=doc.getRootElement();
            
for (Iterator iter = root.elementIterator(); iter.hasNext();) {
                Element element 
= (Element) iter.next();
                
if(element.getName().equalsIgnoreCase("bean"&& element.attributeValue("table").equalsIgnoreCase(tablename)){
                    beanname
=element.attributeValue("class");
                    
for(Iterator it=element.elementIterator();it.hasNext();){
                        count
++;
                        Element elepro
=(Element) it.next();
                        String attName
=elepro.attributeValue("name");
                        String attType
=elepro.attributeValue("type");
                        attrList.add(attName
+":"+attType);
                    }

                }

                
            }

        }
 catch (DocumentException e) {
            
// TODO 自动生成 catch 块
            e.printStackTrace();
        }

        
return beanname;
    }



    
public List getAttrList() {
        
return attrList;
    }



    
public int getCount() {
        
return count;
    }



    
public void setCount(int count) {
        
this.count = count;
    }



}

 

package  test;

public   class  Item  {
    
private int id;
    
private String name;
    
private String description;
    
private double price;
    
public String getDescription() {
        
return description;
    }

    
public void setDescription(String description) {
        
this.description = description;
    }

    
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 double getPrice() {
        
return price;
    }

    
public void setPrice(double price) {
        
this.price = price;
    }

}

 

package  test;
import  java.util. * ;
import  java.lang.reflect.Modifier;
import  java.sql. * ;

import  com.microsoft.jdbc.base.BasePreparedStatement;

public   class  GetList  {
    
public List getRes(String sql) throws Exception{
        List result
=new ArrayList();
        Connection con
=getConnection();
        PreparedStatement pstm
=con.prepareStatement(sql);
        ResultSet rs
=pstm.executeQuery();
//        System.out.println("dfdfd");
        while(rs.next()){
            ResultSetMetaData metadata
=rs.getMetaData();
            
for(int i=1;i<=metadata.getColumnCount();i++){
                String colname
=metadata.getColumnName(i);
                Object colvalue
=rs.getObject(colname);
                
int coltype=metadata.getColumnType(i);    
                result.add(colname
+"="+colvalue);
//                System.out.println(coltype+":"+metadata.getColumnName(i)+rs.getObject(metadata.getColumnName(i)));
            }

        }

        
return result;
    }

    
    
public Connection getConnection(){
        Connection con
=null;
        String url
="jdbc:microsoft:sqlserver://localhost;DatabaseName=pubs";
        
try {
            Class.forName(
"com.microsoft.jdbc.sqlserver.SQLServerDriver");
            con
=DriverManager.getConnection(url,"sa","");
        }
 catch (Exception e) {
            e.printStackTrace();
        }

        
return con;
    }

        
    
/**
     * 
@param args
     * 
@throws Exception 
     
*/

    
public static void main(String[] args) throws Exception {
        GetList list
=new GetList();
//        list.getRes("select * from item");
//        list.Insert();
        

    }


}

 

package  test;

import  java.lang.reflect. * ;
import  java.util. * ;

public   class  BeanDemo  {
    
    
public List newInstance(String sqlId){
        
//定义一个集合保存bean的实例
        List bean=new ArrayList();
        
try {
            XMLParse xmlparse
=new XMLParse();
            GetList gi
=new GetList();
            
//这里是用户在XML文件中配置的sql语句的ID,根据这个ID获得sql语句
            String strSql=xmlparse.getSql(sqlId);
            String tablename
=xmlparse.getTablename();
            
//这里是通过表名获得bean的名字
            String beanname=xmlparse.getBeanname(tablename);
            
//获得字段的个数
            int count=xmlparse.getCount();
            
            
//返回bean里面的属性的集合,可以看到是键值对的形式,bean的属性的类型和名字
            
//然后可以根据类型判断它的具体的类型(太麻烦了就没写了)...
//            List attrList=xmlparse.getAttrList();
//            String[] strAttrs=new String[attrList.size()];
//            for (int i=0;i<attrList.size();i++) {
//                String attr = (String) attrList.get(i);
//                strAttrs[i]=attr;
//            }
//            System.out.println(strAttrs[1]);
            
            
//根据bean的名字得到类对象
            Class obj=Class.forName(beanname);
            
//定义一个集合保存SQL查询出来的集合
            List list=null;
            
if(strSql!=null){
                list
=gi.getRes(strSql);
            }

            
            
//定义bean的Object类型的实例,因为这里我们根本就还不知道它里面的属性和方法,要利用
            
//反射为它赋值
            Object item=null;
            
//遍历结果集
            for(int i=0;i<list.size();i++){
                
//根据字段的个数count,每隔count就创建一个新的bean
                if(i%count==0){
                    item
=obj.newInstance();
                }

                
//获得bean的方法列表
                Method[] methods=item.getClass().getMethods();
                
                
//注意我们返回的结果集是字段名+值的键值对形式,所以要用sal[]数组来截取
                String sqlstr=(String) list.get(i);
                String sql[]
=sqlstr.split("=");
                
//                for(int k=0;k<strAttrs.length;k++){
//                    String[] strAttr=strAttrs[i].split(":");
//                    if(sql[0].equalsIgnoreCase(strAttr[0])){
//                        if("String".equalsIgnoreCase(strAttr[1])){
//                            Class[] parm=new Class[]{new String(sql[0]).getClass()};
//                            item.getClass().getMethod("set"+strAttr[0], parm);
//                        }
//                    }
//                }
                
//                这里定义两个变量是保存截取后的set方法,我把set方法截取就可以获得set方法和set的字段
                String setstr=null;
                String newstr
=null;
                
                
//遍历未知bean的所有方法以确定哪个set方法为当前的结果集所调用
                for(int j=0;j<methods.length;j++){
                    
//截取方法:如:setId()截取后变为set和Id,这样就可以判断方法名和字段名
                    
//再去和返回的结果集匹配
                    setstr=methods[j].getName().substring(0,3);
                    newstr
=methods[j].getName().substring(3);
                    
                    
//判断和结果集字段匹配的set方法
                    if(setstr.equalsIgnoreCase("set"&& newstr.equalsIgnoreCase(sql[0])){
//                        System.out.println(":::");
                        
//不同结果的返回值类型有所不同,这里原来应该对返回的参数的类型进行判断
                        
//后再创建具体的方法参数类型,但太麻烦了所以就直接写的,要是bean里全部定义
                        
//为String类型也OK,就省了判断的那个麻烦的过程了
                        if(newstr.equalsIgnoreCase("id")){
                            Object[] parm
=new Object[]{new Integer(sql[1])};
                            
//利用反射调用未知bean的set方法为它赋值
                            methods[j].invoke(item,parm);
//                            System.out.println("1");
                        }

                        
if(newstr.equalsIgnoreCase("name")){
                            Object[] parm
=new Object[]{new String(sql[1])};
                            methods[j].invoke(item,parm);
//                            System.out.println("2");
                        }

                        
if(newstr.equalsIgnoreCase("description")){
                            Object[] parm
=new Object[]{new String(sql[1])};
                            methods[j].invoke(item,parm);
//                            System.out.println("3");
                        }

                        
if(newstr.equalsIgnoreCase("price")){
                            Object[] parm
=new Object[]{new Double(sql[1])};
                            methods[j].invoke(item,parm);
//                            System.out.println("4");
                        }

                    }

                }

                
//根据字段大概每循环count次一个未知bean的赋值工作就完成了,就可以把它保存进集合中了
                
//注意这时候bean还只是为Object类型,所以未知bean创建好后,就可以直接遍历取出并
                
//进行转型,就可以直接使用了!
                if(i%count==0){
                    bean.add(item);
//                    System.out.println("11111");
                }

//                System.out.println(setstr+newstr);
            }

        }
 catch (Exception e) {
            e.printStackTrace();
        }

        
return bean;
    }

    
    
public void setBean(){
        
    }

    
    
public static void main(String[] args) {
        BeanDemo bean
=new BeanDemo();
        List list
=bean.newInstance("selAll");
        
//遍历转型
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Item it
= (Item) iter.next();
            System.out.println(it.getId()
+" : "+it.getName()+" : "+it.getDescription()+" : "+it.getPrice());
        }


    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值