[动态代理]详解, 速领~~

广告位

  一.简述及实现原则 1.简述 代理模式的一种,指在在不改变 原有类的情况下,在程序运行期间,动态…

 

一.简述及实现原则

1.简述

代理模式的一种,指在在不改变 情况下,程序运行期间,动态增强某个对象的功能。

动态代理中:

待增强的对象 叫做 被代理对象

增强功能的对象   叫做 代理对象

例如:缴话费

被代理对象 : 营业厅 — 缴话费

代理对象:代缴话费的网店、代缴话费APP — 足不出户,缴话费

  • 代理:代为处理。

2.实现原则:

  1. 获取被代理对象
  2. 通过Proxy.newInstance方法创建代理对象
  3. 代理对象获取被代理对象的所有接口,用于代理
  4. 实现InvocationHandler接口,进行功能增强

二.入门案例

[动态代理]详解, 速领~~

  • 现在要求对HWPhone的sendMsg方法进行增强,原有效果为”发送短信”

增强后效果为:

发送短信

(o゜▽゜)o☆[BINGO!]

分析:

  1. 测试类中,获取被代理对象
  2. 根据被代理对象,创建代理对象
  3. 使用代理对象调用sendMsg方法

代码实现:

测试类:

public static void main(String[] args) {     //1、获取被代理对象     final Phone hw = new HWPhone();     //2、根据被代理对象,创建代理对象     //参数一:获取当前类的 类加载器     //参数二:获取 被代理对象 的所有接口     //参数三:实现InvocationHandler接口,用于进行功能增强     Phone obj = (Phone) Proxy.newProxyInstance(Demo1.class.getClassLoader(),             hw.getClass().getInterfaces(),             new InvocationHandler() {                 /**                  * 每次代理对象调用任意方法,都会执行invoke方法                  * @param proxy   代理对象(一般没用)                  * @param method  当前被调用的 被代理对象方法                  * @param args    当前被调用的 被代理对象方法 的参数                  * @return         代理对象方法  的 返回值                  * @throws Throwable                  */                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                     //1、根据方法名判断,如果是sendMsg方法,增强                     if(method.getName().equals("sendMsg")){                         //1.1、调用之前方法                         method.invoke(hw,args);                         //1.2、增强代码                         System.out.println("(o゜▽゜)o☆[BINGO!]");                         //因为sendMsg方法没有返回值的                         return null;                     }                     //2、如果不是sendMsg方法,调用之前方法                     return method.invoke(hw,args);                 }             });     //3、使用代理对象调用增强方法     //发现代理对象调用任何方法,都是在调用InvocationHandler中的invoke方法     obj.call("12345");     obj.sendMsg(); } 

小结:

动态代理:

  1. 获取被代理对象
  2. 根据被代理对象 创建 代理对象
  3. 代理对象调用增强方法即可

注意:代理对象调用任何方法,都在执行invoke

[动态代理]详解, 速领~~

三.​​​​​​使用动态代理修改连接池

增强Connection 对象close方法,不是关闭资源,而是归还连接池

分析:

  1. 在MyDataSource类中,获取被代理对象 Connection对象
  2. 根据被代理对象,创建代理对象
  3. 编写InvocationHandler接口中的invoke方法

MyDataSource类:

 public class MyDataSource implements DataSource {     private static final String DRIVERCLASS="com.mysql.jdbc.Driver";     private static final String URL="jdbc:mysql://127.0.0.1:3306/day01_db";     private static final String USERNAME="root";     private static final String PASSWORD="1234";     //连接池     private static final LinkedList<Connection> pool = new LinkedList<Connection>();     static{         //1、注册驱动         try {             Class.forName(DRIVERCLASS);             //2、初始化连接池,默认连接池有5个连接             initPool();         } catch (Exception e) {             e.printStackTrace();         }     }      /**      * 初始化连接池      */     private static void initPool() throws SQLException {         for (int i = 0; i <5 ; i++) {             pool.addLast(getCon());         }     }     /**      * 类内部进行获取连接的方法      * @return      */     private static Connection getCon() throws SQLException {         //1、获取被代理对象         final Connection con = DriverManager.getConnection(URL, USERNAME, PASSWORD);         //2、根据被代理对象,创建代理对象         Connection result = (Connection) Proxy.newProxyInstance(MyDataSource.class.getClassLoader(),                 con.getClass().getInterfaces(),                 new InvocationHandler() {                     //3、编写invocationHandler中的invoke方法                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                         //3.1、如果是close方法,归还连接池                         if(method.getName().equals("close")){                             pool.addLast(con);                             return null;//close方法没有返回值                         }                         //3.2、如果不是close方法,正常按原代码执行即可                         return method.invoke(con,args);                     }                 });         return result;     }      /**      * 获取连接      * @return      * @throws SQLException      */     public Connection getConnection() throws SQLException {         //判断:连接池是否有连接         if(pool.size()==0){             //连接池没有连接,再创建5个             initPool();         }         //连接池有连接,从池中取出一个连接         return pool.removeLast();     }      /**      * 关闭所有资源 (con对象 归还到 连接池中)      * @param con      * @param ps      * @param rs      * @throws SQLException      */     public static void closeAll(Connection con, PreparedStatement ps,ResultSet rs) throws SQLException {         if(rs!=null)             rs.close();         if(ps!=null)             ps.close();         if(con!=null)             pool.addLast(con);     }      public Connection getConnection(String username, String password) throws SQLException {         return null;     }      public <T> T unwrap(Class<T> iface) throws SQLException {         return null;     }      public boolean isWrapperFor(Class<?> iface) throws SQLException {         return false;     }      public PrintWriter getLogWriter() throws SQLException {         return null;     }      public void setLogWriter(PrintWriter out) throws SQLException {      }      public void setLoginTimeout(int seconds) throws SQLException {      }      public int getLoginTimeout() throws SQLException {         return 0;     }      public Logger getParentLogger() throws SQLFeatureNotSupportedException {         return null;     } } 

看完恭喜你,又知道了一点点!!!

你知道的越多,不知道的越多! 

~感谢志同道合的你阅读,  你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!

女人的秘密

关于作者: 女人的秘密

为您推荐