1.Mybatis相比于jdbc的优势
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1、加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//2、通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis", "root", "root");
//3、定义sql语句 ?表示占位符
String sql = "select * from user where id = ?";
//4、获取预处理preparedStatement
preparedStatement = connection.prepareStatement(sql);
//5、设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, id);
//6、向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//7、遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//8、释放资源
if(resultSet!=null){
try {
resultSet.close();//释放结果集
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();//关闭数据库连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
mybatis相对jdbc的优势:
1.mybatis将数据库连接的信息写在配置文件中,方便维护;
2.mybatis执行的sql语句都是通过配置文件进行配置,不需要写在java代码中。
3.mybatis的连接池管理、缓存管理可以减少连接的频繁创建和关闭,提高查询效率。
2.动态代理
代理概念【什么是代理?】
代理类似于生活中的代购或者是中介,比如买家和卖家,卖家就是商品的代理,个人买东西是无法接触到厂家的。
代理模式即是指为其它对象提供一种代理,以控制对这个对象的访问。
代理对象在客户端和目标对象之间起到中介作用,使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象
- 功能增强:在原有功能的基础上增加了一些额外的功能;
- 控制访问:代理类不让访问目标对象
代理分类【静态代理和动态代理】
1. 静态代理(static-proxy):代理类是自己手工实现的,自己创建一个java类作为代理类;
- 特点:实现简单,容易理解
- 举例说明:卖u盘
步骤:1.定义接口,接口里面定义方法——商家和厂家的行为(可以定义多个方法,表示功能的接口)
2.定义一个厂家的实现类(目标类),不支持用户的 单独购买
3.定义一个商家也实现接口,调用厂家的方法,加价操作(增强功能)
4.测试类购买u盘调用商家的方法- 代理类完成的功能:调用目标对象的方法 AND 功能增强
- 静态代理的优缺点:
目标类增加了,代理类可能需要成倍的增加,代理类数量过多;
当接口中增加了方法(功能),所有代理类也都要实现该方法,影响较多,不方便维护和管理。2.动态代理(dynamic-proxy):动态代理实在程序的执行过程中使用jdk的反射机制创建代理类对象,并动态的指定要代理的目标类。换句话说,动态代理是一种创建java对象的能力,使得不用创建代理类就可以创建代理对象。
在静态代理中目标类很多的时候,可以使用动态代理,避免静态代理的缺点;动态代理中目标类即使很多,代理类数量可以很少,修改接口中的方法时,不会影响代理类
动态代理的两种方式
1.jdk动态代理(掌握)
- jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
2.cglib动态代理(了解)
- cglib是第三方的工具库,创建代理对象,
cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改。因为cglib是继承,重写方法,所以要求目标类不能是fina1的,方法也不能是final的。cglib的要求目标类比较宽松,只要能继承就可以了。cglib在很多的框架中使用,比如mybatis,spring框架中都有使用
jdk动态代理的实现
java.lang.reflect包下有3个类InvocationHandler,Method,Proxy
- InvocationHandler:是一个接口,有一个方法invoke,在invoke方法中完成代理类的功能, 调用目标方法,增强功能
- Method:方法类,method.invoke(目标对象,参数),调用目标类中的方法
object ret= method. invoke(service22,“李四”)- Proxy:代理类,创建代理对象,取代new创建对象的方式。调用静态方法newProxyInstance(),方法原型
public static Object newProxyInstance( ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
参数:1. ClassLoader loader类加载器,负责向内存中加载对象,使用反射机制获取对象的classLoader,类 a, a.getCalss().getClassLoader(),目标对象的类加载器
2.Class<?>[] interfaces: 接口,目标对象实现的接口,也是反射获取的
3.InvocationHandler h : 我们自己写的,代理类要完成的功能
返回值也就是代理对象。
简单来说jdk动态代理就是有固定的模式,我们不需要写代理类,将增强的部分写在InvocationHandler的invoke方法里即可。再利用Pxoxy.newProxyInstance获取目标对象,再调用方法即可。
代码实现
// 接口
public interface UsbSell {
float sell(int amount);
}
// 目标类实现接口
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
System.out.println("目标类中,执行了sell目标方法");
return 85.02f;
}
}
public class MyHandle implements InvocationHandler {
public MyHandle(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res =null;
res = method.invoke(target,args); //待执行目标方法,执行后返回值
// 增强方法
if(res!=null){
Float price = (Float)res;
price = price + 25;
res = price;
}
return res;
}
}
public class MainShop {
public static void main(String[] args){
// 1.创建对象,使用Proxy
// 2.创建目标对象
UsbSell factory = new UsbKingFactory();
// 3.创建Invocationhandler对象
InvocationHandler myHandle = new MyHandle(factory);
// 4.创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
myHandle);
// 通过代理执行方法
float price = proxy.sell(1);
System.out.println("通过动态代理对象,调用方法:" +price);
}
}