您的位置:首页 > 游戏 > 游戏 > 海口模板建站定制_互联网人工智能_推广自己的产品_策划方案模板

海口模板建站定制_互联网人工智能_推广自己的产品_策划方案模板

2025/4/2 23:38:48 来源:https://blog.csdn.net/qq_74092815/article/details/146687383  浏览:    关键词:海口模板建站定制_互联网人工智能_推广自己的产品_策划方案模板
海口模板建站定制_互联网人工智能_推广自己的产品_策划方案模板

JDBC优化时候,我们是可以通过反射和元数据来对相关的方法实现封装。

/*** 执行数据库的DML操作* @return*/
public static Integer update(String sql,Object ... parameter) throws Exception{conn = getConnection();PreparedStatement ps = conn.prepareStatement(sql);if(parameter != null && parameter.length > 0){for (int i = 0; i < parameter.length; i++) {ps.setObject(i+1,parameter[i]);}}int i = ps.executeUpdate();close(conn,ps);return i;
}/*** 查询方法的简易封装* @param sql* @param clazz* @param parameter* @param <T>* @return* @throws Exception*/
public static <T> List<T> query(String sql, Class clazz, Object ... parameter) throws  Exception{conn = getConnection();PreparedStatement ps = conn.prepareStatement(sql);if(parameter != null && parameter.length > 0){for (int i = 0; i < parameter.length; i++) {ps.setObject(i+1,parameter[i]);}}ResultSet rs = ps.executeQuery();// 获取对应的表结构的元数据ResultSetMetaData metaData = ps.getMetaData();List<T> list = new ArrayList<>();while(rs.next()){// 根据 字段名称获取对应的值 然后将数据要封装到对应的对象中int columnCount = metaData.getColumnCount();Object o = clazz.newInstance();for (int i = 1; i < columnCount+1; i++) {// 根据每列的名称获取对应的值String columnName = metaData.getColumnName(i);Object columnValue = rs.getObject(columnName);setFieldValueForColumn(o,columnName,columnValue);}list.add((T) o);}return list;
}/*** 根据字段名称设置 对象的属性* @param o* @param columnName*/
private static void setFieldValueForColumn(Object o, String columnName,Object columnValue) {Class<?> clazz = o.getClass();try {// 根据字段获取属性Field field = clazz.getDeclaredField(columnName);// 私有属性放开权限field.setAccessible(true);field.set(o,columnValue);field.setAccessible(false);}catch (Exception e){// 说明不存在 那就将 _ 转换为 驼峰命名法  user_name  --> userNameif(columnName.contains("_")){Pattern linePattern = Pattern.compile("_(\\w)");columnName = columnName.toLowerCase();Matcher matcher = linePattern.matcher(columnName);StringBuffer sb = new StringBuffer();while (matcher.find()) {matcher.appendReplacement(sb, matcher.group(1).toUpperCase());}matcher.appendTail(sb);// 再次调用复制操作setFieldValueForColumn(o,sb.toString(),columnValue);}}
}

在Mybatis中,参数处理与结果集映射等操作也使用了大量的反射操作。为了简化反射操作的相关代码,Mybatis提供专门的反射模块,将常见的反射行为做进一步封装,提供反射的API。那么,本文的研究内容就聚焦于Mybatis是如何实现反射模块的。

整体的反射模块如图所示

主要涉及到:Reflector、ReflectorFactory、Invoker、MetaClass、MetaObject

然后我们再回过头分析发射模块在Mybatis核心流程中的应用。

  • Reflector是反射模块的基础,每个Reflector对象都对应一个类,在Reflector中缓存了反射需要使用的类的元信息

  • ReflectorFactory接口主要实现了对Reflector对象的创建和缓存

  • Invoker针对于Class中Field和Method的调用,在MyBatis中封装了Invoker对象来统一处理(有使用到适配器模式)

  • 在Reflector中可以针对普通的属性操作,但是如果出现了比较复杂的属性,比如 private Person person; 这种,我们要查找的表达式 person.userName.针对这种表达式的处理,这时就可以通过MetaClass来处理了。

  • 通过MetaObject对象解析复杂的表达式来对提供的对象进行操作。

Reflector

Reflector是反射模块的基础,每个Reflector对象都对应一个类,在Reflector中缓存了反射需要使用的类的元信息。

其中,构造方法中实现相关属性的初始化

Reflector对外提供的方法

方法名称作用
getType获取Reflector表示的Class
getDefaultConstructor获取默认的构造器
hasDefaultConstructor判断是否有默认的构造器
getSetInvoker根据属性名称获取对应的Invoker 对象
getGetInvoker根据属性名称获取对应的Invoker对象
getSetterType获取属性对应的类型 比如: String name; // getSetterType("name") --> java.lang.String
getGetterType与上面是对应的
getGetablePropertyNames获取所有的可读属性名称的集合
getSetablePropertyNames获取所有的可写属性名称的集合
hasSetter判断是否具有某个可写的属性
hasGetter判断是否具有某个可读的属性
findPropertyName根据名称查找属性

ReflectorFactory

ReflectorFactory接口主要实现了对Reflector对象的创建和缓存

DefaultReflectorFactory

Mybatis中只提供了这种工厂,创建Reflector对象。

Invoker

针对于Class中Field和Method的调用,在MyBatis中封装了Invoker对象来统一处理(涉及到【适配器模式】)

MetaClass

在Reflector中可以针对普通的属性操作,但是如果出现了比较复杂的属性,比如 private Person person; 这种,我们要查找的表达式 person.userName.针对这种表达式的处理,这时就可以通过MetaClass来处理了。我们来看看主要的属性和构造方法

// 主要是实现对于 复杂对象 的方法的访问
// 比如 自定义对象;集合----
public class RichType {private RichType richType;// 方法...
}
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);System.out.println(meta.hasGetter("richField"));System.out.println(meta.hasGetter("richType.richField"));// findProperty 只能处理 . 的表达式System.out.println(meta.findProperty("richType.richProperty"));System.out.println(Arrays.toString(meta.getGetterNames()));

MetaObject

通过MetaObject对象解析复杂的表达式来对提供的对象进行操作。具体的通过案例来演示会更直观些。

    @Testpublic void shouldGetAndSetField() {RichType rich = new RichType();MetaObject meta = SystemMetaObject.forObject(rich);meta.setValue("richField", "foo");System.out.println(meta.getValue("richField"));}@Testpublic void shouldGetAndSetNestedField() {RichType rich = new RichType();MetaObject meta = SystemMetaObject.forObject(rich);meta.setValue("richType.richField", "foo");System.out.println(meta.getValue("richType.richField"));}@Testpublic void shouldGetAndSetMapPairUsingArraySyntax() {RichType rich = new RichType();MetaObject meta = SystemMetaObject.forObject(rich);meta.setValue("richMap[key]", "foo");System.out.println(meta.getValue("richMap[key]"));}输出均为 foo

Mybatis核心流程中怎么实际应用反射模块?

在创建SqlSessionFactory操作的时候会完成Configuration对象的创建,而在Configuration中默认定义的ReflectorFactory的实现就是DefaultReflectorFactory对象

然后在解析全局配置文件的代码中,给用户提供了ReflectorFactory的扩展,也就是我们在全局配置文件中可以通过reflectorFactory标签来使用我们自定义的ReflectorFactory

执行SQL

在Statement获取结果集后,在做结果集映射的使用有使用到,在DefaultResultSetHandler的createResultObject方法中。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com