在最初接触动态代理时,是在学习数据库连接池时,作为归还连接的一个最好用也是最常用的方法。用一句话来概括就是在不改变目标对象方法的情况下对方法进行增强。这就不得不来说一下数据库连接池了。
所谓数据库连接池,用我自己的理解来看,就是存放数据库连接对象的容器。如果每次后台访问数据库都要先创建数据库连接,用完之后再关闭连接,这样对于频繁访问数据库的程序来说,无疑会给系统带来巨大压力,为了解决这个问题,结合池化思想,提出数据库连接池的概念。把数据库连接对象放进指定容器中,用到时从池中获取连接,用完之后再归还到池子里,这样就避免了反复创建对象和关闭连接。以下就是创建和实现的过程:
数据库连接池
负责分配、管理和释放数据库连接,允许应用程序重复使用一个现有的数据库连接。
DataSource(接口)
数据源(数据库连接池),Java官方提供的数据库连接池规范。、
Connection getConnection()方法:获取数据库连接对象(核心功能)
自定义数据库连接池
1.定义一个类,实现DataSource接口。
2.定义一个容器,用于保存多个Connection连接对象。
List<Connection> pool = Collections.synchronizedList(new ArrayList<>());
3.定义静态代码块,通过JDBC工具类获取10个连接保存到容器中。
static{
10.fori
Connection con = JDBCUtils.getConenction();
pool.add(con);
}
4.重写getConnection方法,从容器中获取一个连接并返回。
if(pool.size()>0){
Connection con = pool.remove(0);
return con;
}else{
throw new RuntimeException("连接数量已用尽");
}
5.定义getSize方法,用于获取容器的大小并返回。
public int getSsize(){
return pool.size();
}
归还连接
1.继承方式(行不通)
继承JDBC4Connection类,重写close()方法,完成对象连接的归还。
实现步骤:
1 定义一个类,继承JDBC4Connection。
2 定义Connection连接对象和连接池容器对象的成员变量。
3 通过有参构造方法完成对成员变量的赋值。
4 重写close方法,将连接对象添加到池中。
2.装饰设计模式(有大量方法要重写)
在不改变现有对象原有结构的情况下,动态的给该对象增加一些职责(增加额外功能)。
实现思路:
1.定义一个类,实现和被装饰类相同的接口。
2.在类中声明一个原有对象的成员变量。
3.通过有参构造方法为其赋值。
4.重写方法,不想改进的方法继续调用原有对象中的功能,想改进的方法自己重写。
3.适配器设计模式(适配器类还需要自己编写,麻烦)
解决接口和实现类之间的矛盾问题。
实现思路:
1.定义一个适配器类,实现对应接口。
2.重写所有的抽象方法。
3.让功能类继承适配器类,重写自己需要的方法。
4.为了避免其他类来创建适配器对象,该适配器类需要定义为抽象类。
4.动态代理方式(自己写的连接池技术不够完善,功能也不够强大)
在不改变目标对象方法的情况下对方法进行增强
组成:
被代理对象:真实的对象
代理对象:内存中的一个对象
要求:
代理对象必须和被代理对象实现相同的接口
实现:
Proxy.newProxyInstance(类加载器 接口类型Class数组 代理规则{
@Override
public Object invoke(Object proxy,Method,Object[] args) throws Throwable(
)
});
类加载器:con.getClass().getClassLoader()
接口类型Class数组:new Class[]{Connection.class}
代理规则:new InvocationHandler(){
//执行Connection实现类连接对象所有的方法都会经过invoke
//如果是想要重写的方法,则重写;如果不是,直接执行连接对象原有的功能即可
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throws Throwable{
}
}
动态代理方式归还数据库连接实现步骤:
1.定义一个类,实现DataSource接口
2.定义一个容器,用于保存多个Connection连接对象
3.定义静态代码块,通过JDBC工具类获取10个连接保存到容器中
4.重写getConnection方法,从容器中获取一个连接
5.通过Proxy代理,如果是close方法,就将连接归还池中,如果是其他方法则调用原有功能
Connection proxyCon = (Connection)Proxy.newProxyInstance(con.getClass().getClassLoader() , new Class[]{Connection.class} , new InvocationHandler(){
//执行Connection实现类连接对象所有的方法都会经过invoke
//如果是想要重写的方法,则重写;如果不是,直接执行连接对象原有的功能即可
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throws Throwable{
if(method.getName().equals("close")){
pool.add(con);
return null;
}else{
return method.invoke(con,args);
}
}
});
6.定义getSize方法,用于获取容器的方法并返回