代理模式
需求:对系统中已有的某个类的功能,进行扩展(增强)
要求:在不修改源码的情况下,对已有的功能进行增强
静态代理
抽象接口:保证包含增强功能的对象和原有功能的对象,对外提供相同的方法
目标对象:封装了原有功能
代理对象:封装了增强功能和原有功能(通过持有一个目标对象的引用实现)
问题:代码不够灵活,产生大量冗余工作
动态代理
动态代理的实现API:
Proxy :
帮助程员产生代理对象,提供产生代理类和代理对象的静态方法
InvocationHandler :
句柄接口,拦截到,所有代理对象调用的方法(所有代理对象调用的方法,都可以被
InvocationHandler拦截到)
模拟实现数据库连接池
数据库的操作:考虑性能问题
频繁的连接和断开数据,本身很消耗资源(操作数据的性能)
---对数据库连接对象,进行池管理(由池中获得资源,用完之后将资源再次放入)
连接池的具体实现:
1 创建一个集合对象,封装n个Connection对象
2 定义获得连接
3 和归还连接的功能
实现代码:
1 public class DBPoolUtils {
2 private static String driver;
3 private static String url;
4 private static String username;
5 private static String password;
6 private static int maxconn;//线程池最大的连接数
7
8 //定义一个集合表示线程池
9 static List<Connection> list=new ArrayList<Connection>();
10 //类加载的时候就初始化,创建好连接对象
11 static{
12 Properties properties=new Properties();
13 try {
14 //读取配置文件信息
15 properties.load(DBPoolUtils.class.getResourceAsStream("mysql.properties"));
16 driver=properties.getProperty("driver");
17 url=properties.getProperty("url");
18 username=properties.getProperty("username");
19 password=properties.getProperty("password");
20 maxconn=Integer.parseInt(properties.getProperty("maxconn"));
21 Class.forName(driver);
22 /*
23 * 创建连接对象
24 * 因为当用户关闭的时候要把线程连接对象还到线程池中,
25 * 所有拿到的对象与还回来的对象都应该是代理对象。
26 * 对close()方法进行拦截,把原来断开连接改成将线程连接对象还到连接池
27 */
28 for (int i = 0; i < maxconn; i++) {
29 final Connection conn=DriverManager.getConnection(url, username, password);
30 //创建代理对象
31 Object connProxy=Proxy.newProxyInstance(
32 DBPoolUtils.class.getClassLoader(),//自定义类的类加载器
33 new Class<?>[]{Connection.class},//实现的接口的class文件数组
34 new InvocationHandler() {//匿名内部类实现InvocationHandler
35
36 @Override
37 public Object invoke(
38 Object proxy,//代理对象
39 Method method,//代理对象实现接口中调用的方法
40 Object[] args//代理对象实现接口中调用的方法中的参数
41 )throws Throwable {
42 //拦截close()方法,将原来的断开连接改为还回连接池,即:将当前的代理对象加到线程池中
43 String methodName=method.getName();
44 if ("close".equals(methodName)) {
45 list.add((Connection) proxy);
46 //唤醒等待的线程
47 synchronized (list) {
48 list.notifyAll();
49 }
50 }
51 //放行:调用原来的对象方法
52 Object obj=method.invoke(conn, args);
53 return obj;
54 }
55 });
56 //将创建好的代理线程对象加线程池
57 list.add((Connection) connProxy);
58 }
59 } catch (IOException e) {
60 e.printStackTrace();
61 } catch (ClassNotFoundException e) {
62 e.printStackTrace();
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67 /**
68 * 对外提供一个连接对象
69 * @return
70 */
71 public static Connection getConnection(){
72 //当线程池中没有连接对象的时候,让线程等待,而不报异常,等待其他线程返回时再唤醒
73 synchronized (list) {
74 if (list.size()==0) {
75 try {
76 list.wait();
77 } catch (InterruptedException e) {
78 e.printStackTrace();
79 }
80 }
81 }
82 //每次从线程池中取出第一个线程
83 Connection conn=list.remove(0);
84 System.out.println("剩余:"+list.size());
85 return conn;
86 }
87 }