这次我最快

飞的起来
应该飞的起来
碧海蓝天
只等风的到来


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

Jdbc为何需要反射加载驱动

发表于 2020-05-05 | 分类于 java | 阅读次数:

看了好多反射机制的东西,感觉如果一个类的某些方法被设为私有的时候我们可以使用反射机制去访问。但是为什么jdbc驱动也都是使用反射机制去访问,很费解

我想题主想问的是如下代码为何要使用反射:

1
2
3
4
5
6
try {
Class.forName("com.mysql.jdbc.Driver") ;
} catch(ClassNotFoundException e) {
System.out.println("找不到驱动程序类 ,加载驱动失败!");
return; // or do something else
}

多年前写JDBC时年少无知,没有想过这个问题,今天题主提出来,觉得这个问题很好。

基本原因

首先,上面一段代码的主要作用,是在运行期以反射的方式来检查JDBC驱动的主类com.mysql.jdbc.Driver是否存在,若不存则表示运行环境中没有这个驱动,进入catch段。如果你确定一定以及肯定它会存在,可以直接写成

1
import com.mysql.jdbc.Driver;

效果基本是一样的(只是在编译期及运行期要都保证此类存在classpath中)

所以,以反射形式加载的一个好处是当驱动jar包不存在时,我们可以做更多的操作。(要知道,在很久很久以前,jdbc驱动一般都是放在运行环境的classpath中的,如tomcat/lib)

另一个原因

如果你是一个有追求的程序员,那么另外一个很重要的原因是解耦。

首先要明白JDBC是Java的一种规范,通俗一点说就是JDK在java.sql.*下提供了一系列的接口(interface),但没有提供任何实现(也就是类)。 所以任何人都可以在接口规范之下写自己的JDBC实现(如MySQL)。而若调用者也只调用接口上的方法(如我们),那么当未来有任何变更需要时(例如要从MySQL迁移至Oracle),则理论上不需要对代码做任何修改就能直接切换(可惜SQL语法没能统一规范)

这意味着什么?意味着你的代码中不应该引用任何与实现相关的东西,你的代码只知道java.sql.*,而不应该知道com.mysql.*或是com.oracle.*,以避免或减少未来切换数据源时对代码的变更。

注意,我们使用的所有其他API包括Connection/Statement/ResultSet等都是java.sql.*的东西,甚至com.mysql.jdbc.Driver类也是:

1
2
3
4
package com.mysql.jdbc;
public class Driver ... implements java.sql.Driver {
...
}

因此,直接import com.mysql.jdbc.Driver;违反了开闭原则(OCP,对扩展开放,对修改关闭)。(有人说我用反射也必须要修改代码呀,事实上你可以将类名字符串存储至.properties文件,和数据库用户名密码放在一起,就像Hibernate做的那样)

引申问题

如果我可以保证JDBC驱动一定在classpath下,是不是可以不写这段反射代码,也不引用任何的Driver类?答案是否定的,请看下面这段代码源自com.mysql.jdbc.Driver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.mysql.jdbc;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
...
}

static代码块会在类加载时就被执行——也就是当我们执行Class.forName("com.mysql.jdbc.Driver")时(或import com.mysql.jdbc.Driver)

转自:https://segmentfault.com/q/1010000000315618

服务治理之服务隔离

发表于 2020-05-01 | 分类于 微服务 | 阅读次数:

背景:

到货提醒、商品列表缓存服务等,需要定时任务离线计算。实现定时任务的方法跟正常线上业务调用的为相同的方法,且为同一模块。为避免离线任务对线上业务造成影响,采用机器注册到不同zk的方式来进行服务隔离。

由此产生了以下问题:

  1. 离线任务较多,且调用量较大,导致下游压力较大
  2. 大部分的机器用来处理离线任务,造成资源浪费
  3. 机器调用量较大,出现线程池打满,任务排队的现象
  4. 服务注册和消费,因为使用的为同一项目,采用修改host的方式来进行了隔离。

解决问题:

针对问题1、2、3,随着APP版本的升级和服务架构的升级,一些支撑老服务的定时任务已经没有使用场景了,进行了下线操作,但是这还是没有从根本上解决问题。

采用了任务打散,调用到脚本集群上,解决单一脚本机器负载较高的问题

使用mq进行削峰

服务隔离的想法:

  1. 打包机新增job profile,将业务和脚本进行分开
  2. 将只提供给脚本服务使用的服务,增加job关键字,比如xxxJobService
  3. 使用服务路由的特性进行业务隔离,解决对机器host的依赖

dubbo知识点导图

发表于 2020-04-21 | 分类于 微服务 | 阅读次数:

dubbo的背景及关键元素

20200505158866815826475.png

dubbo面向使用的导图

20200505158866816266478.png

dubbo开发源码导图

依赖反转

发表于 2020-04-05 | 分类于 cleancode | 阅读次数:

依赖反转:

DIP:依赖反转原则 Dependence Inversion Principle

依赖反转原则主要想告诉我们的是,如果想要设计一个灵活的系统,在源代码层次的依赖关系中就应该多引用抽象类型,而非具体实现。

为什么需要多引用抽象类型:

我们每次修改抽象接口的时候,一定会修改具体实现。

修改具体实现的时候,很少需要修改对应的抽象接口。

优秀的软件设计师和架构师会花费很大精力来设计接口,以减少未来对其进行改动。如果想要在软件架构设计上追求稳定,就必须多使用稳定的抽象接口,少依赖多变的具体实现。

依赖反转设计原则归结为以下几条具体的编码守则:

  1. 多使用稳定的抽象接口,少依赖多变的具体实现。
  2. 不要在具体实现类上创建衍生类
  3. 不要覆盖包含具体实现的函数
  4. 应避免在代码中写入与任何具体实现相关的名字,或者是其他容易变动的事物的名字。

实现细节

发表于 2020-04-05 | 分类于 cleancode | 阅读次数:

本文大部分摘自《架构整洁之道》

数据库只是实现细节

Web是实现细节

应用程序框架是实现细节

本文的核心:

业务和实现细节分离。即实现细节不应该影响到业务架构。

谈一谈依赖反转

设计原则

发表于 2020-04-05 | 分类于 cleancode | 阅读次数:

本文大部分摘自《架构整洁之道》

SRP:单一职责原则 Single responsibility principle

OCP:开闭原则 Open Closed Principle

LSP:里氏替换原则 Interface Segregation Principle

ISP:接口隔离原则 Liskov Substitution Principle

DIP:依赖反转原则 Dependence Inversion Principle

编程范式

发表于 2020-04-05 | 分类于 cleancode | 阅读次数:

本文大部分摘自《架构整洁之道》

本文讲述的三个编程范式,它们分别是结构化编程(structured programming)、面向对象编程(object-oriented programming)以及函数式编程(functional programming)。

结构化编程:

面向对象编程:

函数式编程:

互联网兵种简介

发表于 2020-03-10 | 阅读次数:

互联网兵种简介

上篇文章熟悉了一个程序员教练的重要性。

那么常见健身房里分为有氧运动:跑步、游泳、健身操。无氧运动:撸铁、撸铁、撸铁。

那么教练会问你想练什么。同样的互联网里也会分为多种兵种,你是想做服务端、前端、算法还是啥,刚入门的小白,对此可能一无所知。下面一块了解下吧。

兵种简介

大家看到的一款产品或者新上线的一个功能,需要多个兵种相互配合才能够完成。

  1. 产品:先头部队(调研市场、输出需求)
  2. 设计:阅兵方队(让产品展现优美,交互合理)
  3. 客户端研发:通讯兵(将产品做成APP应用为载体进行传播)
  4. 服务端研发:战斗集群,航空母舰(对数据流转整体服务进行支撑)
  5. DB:弹药库(存储着整体的数据,是公司最为宝贵的财富)
  6. 测试:医疗兵(对产品质量进行把控)
阅读全文 »

Redis sds源码详解

发表于 2019-12-22 | 分类于 redis | 阅读次数:

20191222157701368251284.png

阅读全文 »

Redis知识概览

发表于 2019-12-15 | 分类于 redis | 阅读次数:

玩归玩,闹归闹,别拿学习开玩笑…

写在开头

想必作为一个后端开发对Redis必然不陌生,无论是互联网巨头阿里还是小到十几人的创业公司,都在使用的开源技术。源码地址: https://github.com/antirez/redis 作者:Antirze,帅的不像实力派。

大家都熟悉的redis,基于内存、I/O多路复用、C语言实现、单线程、数据结构简单,这些标签使得Redis名声大噪,广泛使用于各种场景。

那么Redis的整体架构是什么样子的呢,下面通过一张图来详细聊一下。

20191215157641287374646.png

阅读全文 »
12…6
lemon

lemon

坚信我们为爱

57 日志
19 分类
50 标签
GitHub 掘金
友链
  • 游乐鱼的博客
  • 吖吖邦的博客
© 2020 lemon