栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射乃框架的灵魂

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射乃框架的灵魂

反射乃框架的灵魂

接着昨天的文章,今天言何为反射?反射指的是这部分代码,只有在程序运行时,存在某一动作下,会触发执行。这就会带来,不同触发条件下,带来的结果会不同。

1、回顾JDBCUtils
package com.wnx.mall.tiny.fruit.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
	
	public static Connection getConnection() throws SQLException,
				ClassNotFoundException {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/javaweb";
			String username = "root";
	    	String password = "root";
			Connection conn = DriverManager.getConnection(url, username,password);
			return conn;
		}
		
		public static void release(Statement stmt, Connection conn) {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				conn = null;
			}
		}

		
	     public static void release(ResultSet rs, Statement stmt, 
	     		Connection conn){
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				rs = null;
			}
			release(stmt, conn);
		}
}

2、缺点弥补

采用上述方式操作数据库,问题一,数据库IO连接需要耗费大量资源,费时!问题二,该工具类出现的硬编码,没有做到代码和参数的解耦合。

聪明的程序员,想到了数据库连接池的概念来解决IO连接耗费资源的问题。池子中存在许多连接,当使用完这个连接的时候,该连接不会直接销毁,而是放回到池子中,便于程序反复复用之。而硬编码问题,程序员想到将这些参数统一放到XXX.properties文件中,集中管理他们。比如jdbc.properties,就存放了数据库连接的基本参数。

2.1、jdbc.properties
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/javaweb?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
2.2、整合数据库连接池
package com.wnx.mall.tiny.fruit.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
   // 加载驱动,并建立数据库连接
   public static Connection getConnection() throws Exception {
      Properties properties = new Properties();
      properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
      DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
         return dataSource.getConnection();
      }
      // 关闭数据库连接,释放资源
      public static void release(Statement stmt, Connection conn) {
         if (stmt != null) {
            try {
               stmt.close();
            } catch (SQLException e) {
               e.printStackTrace();
            }
            stmt = null;
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException e) {
               e.printStackTrace();
            }
            conn = null;
         }
      }
        public static void release(ResultSet rs, Statement stmt, 
             Connection conn){
         if (rs != null) {
            try {
               rs.close();
            } catch (SQLException e) {
               e.printStackTrace();
            }
            rs = null;
         }
         release(stmt, conn);
      }
}
3、并不能真的优化我们开发体验

虽然上述操作对于程序底层操作做到了资源合理利用,解决了硬编码问题。但是我们业务类还是要写很多冗余的代码。特别是查询,还有遍历结果集,封装到model中,实在啰嗦。而反射便可以有效提高我们开发体验。

3.1、baseDao

定义baseDao,让反射帮我们执行吧!

package com.wnx.mall.tiny.fruit.dao;

import com.wnx.mall.tiny.fruit.utils.JDBCUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public abstract class baseDAO {


    protected Connection conn ;
    protected PreparedStatement psmt ;
    protected ResultSet rs ;

    //T的Class对象
    private Class entityClass ;

    public baseDAO(){
        //getClass() 获取Class对象,当前我们执行的是new FruitDAOImpl() , 创建的是FruitDAOImpl的实例
        //那么子类构造方法内部首先会调用父类(baseDAO)的无参构造方法
        //因此此处的getClass()会被执行,但是getClass获取的是FruitDAOImpl的Class
        //所以getGenericSuperclass()获取到的是baseDAO的Class
        Type genericType = getClass().getGenericSuperclass();
        //ParameterizedType 参数化类型
        Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
        //获取到的中的T的真实的类型
        Type actualType = actualTypeArguments[0];
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected Connection getConn(){
        try {
            return JDBCUtils.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null ;
    }

    protected void close(ResultSet rs , PreparedStatement psmt , Connection conn){
        try {
            if (rs != null) {
                rs.close();
            }
            if(psmt!=null){
                psmt.close();
            }
            if(conn!=null && !conn.isClosed()){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //给预处理命令对象设置参数
    private void setParams(PreparedStatement psmt , Object... params) throws SQLException {
        if(params!=null && params.length>0){
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i+1,params[i]);
            }
        }
    }

    //执行更新,返回影响行数
    protected int executeUpdate(String sql , Object... params){
        boolean insertFlag = false ;
        insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
        try {
            conn = getConn();
            if(insertFlag){
                psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            }else {
                psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            }
            setParams(psmt,params);
            int count = psmt.executeUpdate() ;

            rs = psmt.getGeneratedKeys();
            if(rs.next()){
                return ((Long)rs.getLong(1)).intValue();
            }
            return count ;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            close(rs,psmt,conn);
        }
        return 0;
    }

    //通过反射技术给obj对象的property属性赋propertyValue值
    private void setValue(Object obj ,  String property , Object propertyValue){
        Class clazz = obj.getClass();
        try {
            //获取property这个字符串对应的属性名 , 比如 "fid"  去找 obj对象中的 fid 属性
            Field field = clazz.getDeclaredField(property);
            if(field!=null){
                field.setAccessible(true);
                field.set(obj,propertyValue);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    //执行复杂查询,返回例如统计结果
    protected Object[] executeComplexQuery(String sql , Object... params){
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //通过rs可以获取结果集的元数据
            //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等
            ResultSetmetaData rsmd = rs.getmetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            //6.解析rs
            if(rs.next()){
                for(int i = 0 ; i executeQuery(String sql , Object... params){
        List list = new ArrayList<>();
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //通过rs可以获取结果集的元数据
            //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等

            ResultSetmetaData rsmd = rs.getmetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            //6.解析rs
            while(rs.next()){
                T entity = (T)entityClass.newInstance();

                for(int i = 0 ; i 
3.2、FruitDAOImpl 

再看实现的变化,可以看到,对比之前,我们要写的代码大大减少了!我们的关注点,只在那条最关键的SQL。

package com.wnx.mall.tiny.fruit.dao.impl;

import com.wnx.mall.tiny.fruit.dao.baseDAO;
import com.wnx.mall.tiny.fruit.dao.FruitDAO;
import com.wnx.mall.tiny.fruit.domain.Fruit;
import com.wnx.mall.tiny.fruit.utils.JDBCUtils;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class FruitDAOImpl extends baseDAO implements FruitDAO {


    
    @Override
    public List getFruitList() {
        String sql = "select * from t_fruit";
        return executeQuery(sql);


    }
    
    @Override
    public boolean addFruit(Fruit fruit) {
        String sql = "insert into t_fruit values(0,?,?,?,?)";
        int count = super.executeUpdate(sql, fruit.getFname(), fruit.getPrice(), fruit.getFcount(), fruit.getRemark());
        return count>0;
    }
    
    @Override
    public boolean updateFruit(Fruit fruit) {
        String sql = "update t_fruit set fcount = ? where fid = ? " ;
        int count = super.executeUpdate(sql,fruit.getFcount(),fruit.getFid());
        return count>0;
    }
    
    @Override
    public Fruit getFruitByFname(String fname) {
        String sql = "select * from t_fruit where fname like ? ";
        return load(sql,fname);

    }
    
    @Override
    public boolean delFruit(String fname) {
        String sql = "delete from t_fruit where fname like ? " ;
        int count = executeUpdate(sql, fname);
        return count>0;
    }
    
    @Override
    public boolean delete(int fid) {
        String sql = "delete from t_fruit where fid =  ?  " ;
        int count = super.executeUpdate(sql,fid);
        return count >0;

    }
    
    @Override
    public Fruit findById(int fid) {
        String sql = "select * from t_fruit where  fid =  ? ";
        return load(sql,fid);

    }
}

4、缺点

反射是框架的灵魂,合理的使用框架,能减少我们的代码量。让我们能快速开发。优秀的数据库框架有Apache DbUtils工具类,Spring的JdbcTemplate工具类,Mybatis框架, SpringData Jpa框架。 下一篇文章,我们使用框架进行开发。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732007.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号