代理模式

    科技2025-04-14  14

    文章目录

    静态代理动态代理

    静态代理

    静态代理:自己派生代理类. 代理类与被代理类是同类型的。代理类要持有被代理类。数据库连接池的简单实现,jdbc中Connection对象的close方法为关闭连接,使用连接池,通过代理设置,将close方法覆盖为归还Connection对象到池子里,而非直接关闭连接。 // 创建连接池,容量为10,有getConnection()和returnConnection()方法 public class MyConnectionList { private static LinkedList<Connection> list= new LinkedList<>(); public MyConnectionList(){ try { Class.forName("com.mysql.jdbc.Driver"); for(int i=0;i<10;i++){ //connection是JDBC4Connectin对象。是原生对象,被代理对象 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/704b?characterEncoding=utf8", "root", "root"); //connectionProxy是代理对象. Connection connectionProxy = new ConnectionProxy(connection);//皮包公司-->关联着原生对象了 //把代理对象放集合 list.add(connectionProxy); } } catch (Exception e) { e.printStackTrace(); } } public static void returnConnection(Connection conn){ System.out.println("return begin-->currentSize:"+list.size()); list.add(conn); System.out.println("return end--> currentSize:"+list.size()); } public Connection getConnection(){ System.out.println("currentSize:"+list.size()); Connection connection = list.removeLast(); System.out.println("get--> currentSize:"+list.size()); return connection; } public void printInfo(){ System.out.println("total size:"+list.size()); for (Connection conn:list){ System.out.println(conn); } } } //代理类 public class ConnectionProxy implements Connection { private Connection source; public ConnectionProxy(Connection source) { this.source = source; } // 重写Connection的方法,最关键是close方法 @Override public void close() throws SQLException { //不调用原生的close,想办法放回list集合 System.out.println("-----------close------"); /** * this:当前使用中的Connection对象 * * 加入 * * MyConnectionList中 * */ MyConnectionList.returnConnection(this); } }

    动态代理

    自己不写代理类。在程序运行期间,动态的在虚拟机中生成代理类. jdk:Proxy.要求被代理对象必须有接口(因为代理生成的$Proxy0对象已经继承了Proxy,java不支持多继承)第三方:cglib.被代理对象可以没有接口 public class MyConnectionList2 { private static LinkedList<Connection> list= new LinkedList<>(); public MyConnectionList2(){ try { Class.forName("com.mysql.jdbc.Driver"); for(int i=0;i<10;i++){ //connection是JDBC4Connectin对象。是原生对象,被代理对象 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/704b?characterEncoding=utf8", "root", "root"); //connectionProxy是代理对象. Connection connectionProxy = getConnectionProxy(connection); //把代理对象放集合 list.add(connectionProxy); } } catch (Exception e) { e.printStackTrace(); } } /** * 该方法用来生成source对象的代理对象 * @param source * @return */ public Connection getConnectionProxy(Connection source){ // Proxy.newProxyInstance()需要此三个参数 ClassLoader classLoader = source.getClass().getClassLoader(); Class[] interfaces = new Class[]{Connection.class};//接口类对象,运行期间,从接口派生代理类 InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if(name.equals("close")){ //proxy对象放回池子中 MyConnectionList2.returnConnection((Connection) proxy); return null; }else return method.invoke(source,args);//source.prepareStatemnt("") } }; //返回的就是代理对象(代理对象持有了handler引用地址。当调用代理对象中的方法时,底层调了handler对象中的invoke方法) Connection proxy = (Connection) Proxy.newProxyInstance(classLoader, interfaces, handler); return proxy; } public static void returnConnection(Connection conn){ System.out.println("return begin-->currentSize:"+list.size()); list.add(conn); System.out.println("return end--> currentSize:"+list.size()); } public Connection getConnection(){ System.out.println("currentSize:"+list.size()); Connection connection = list.removeLast(); System.out.println("get--> currentSize:"+list.size()); return connection; } public void printInfo(){ System.out.println("total size:"+list.size()); for (Connection conn:list){ System.out.println(conn); } } } SqlSession.getMapper()的动态代理方式 public class TestGetMapper { public static void main(String[] args) { SqlSessionFactory factory = SessionFactoryUtil.get(); SqlSession session = factory.openSession(); SysuserMapper mapper = getMapper(SysuserMapper.class,session); Sysuser sysuser = mapper.selectUserByKey(1); System.out.println(sysuser); } public static <T> T getMapper(Class<T> clz,SqlSession session){ T t = (T)Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class<?> declaringClass = method.getDeclaringClass(); String name = declaringClass.getName(); String id = name+"."+methodName; MappedStatement mappedStatement = session.getConfiguration().getMappedStatement(id); SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); if(sqlCommandType==SqlCommandType.SELECT){ Class<?> returnType = method.getReturnType(); if(Collection.class.isAssignableFrom(returnType)){ return session.selectList(id,args[0]); }else{ return session.selectOne(id,args[0]); } } return null; } }); return t; } }
    Processed: 0.010, SQL: 8