zoukankan      html  css  js  c++  java
  • 设计模式学习笔记:一、代理模式(动态代理实现)

    以数据库查询为例:

    1.声明接口:执行数据库操作

    public interface SqlSession {
    	
    	 public int save(String sql)throws Exception;
    
    }

    2.接口实现类:具体的主要业务,sql执行的实现

    public class DeptMapper implements SqlSession {
        PreparedStatement ps;
    	@Override
    	public int save(String sql) throws SQLException {//JDBC主要业务 输送sql
    		   int num= ps.executeUpdate(sql);
    		return num;
    	}
    
    }

    3.InvocationHanler接口实现类:次要业务,前期数据库连接,后期sqlsession关闭

    public class Invaction implements InvocationHandler {
    
    	    private SqlSession    obj;//具体被监控对象
    	    Connection connection ;
    	    PreparedStatement pStatement;
    	    
    	    public Invaction(SqlSession param){
    	    	this.obj = param;
    	    }
    	
    	/*
    	 * 
    	 *  invoke方法:在被监控行为将要执行时,会被JVM拦截
    	 *             被监控行为和行为实现方会被作为参数输送invoke
    	 *             ****通知JVM,这个被拦截方法是如何与当前次要业务方法绑定实现 
    	 *  invoke方法三个参数
    	 *  
    	 *           int v= 小明.eat();//JVM拦截
    	 *            eat方法封装为Mehtod类型对象
    	 *            eat方法运行时接受所有的实参封装到Object[]
    	 *            将负责监控小明的代理对象作为invoke方法第一个参数
    	 * 
    	 */
    	@Override
    	public Object invoke(Object porxy, Method method, Object[] params) throws Throwable {
    		         Object value;
    		        //1.执行JDBC初始次要业务
    		            init();
    		        //2.执行JDBC主要业务
    		           Field psField = obj.getClass().getDeclaredField("ps");
    		           psField.setAccessible(true);
    		           psField.set(obj, pStatement);
    		          value= method.invoke(obj, params);
    		        //3.执行JDBC结束次要业务
    		           close();
    		return value; //返回被拦截方法,需要调用地方
    	}
    	
    	//次要业务
    	private void init()throws Exception{
    		Class.forName("com.mysql.jdbc.Driver");
    		 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123");
    	     pStatement = connection.prepareStatement("");
    	}
    	
    	private void close() throws SQLException{
    		if(pStatement!=null){
    			pStatement.close();
    		}
    		if(connection!=null){
    			connection.close();
    		}
    	}
    
    }

    4.代理对象创建

    public class SqlSessionFactory {
    	/*
    	 * 
    	 *  JDK动态代理模式下,代理对象的数据类型
    	 *  应该由监控行为来描述 
    	 *  参数: Class文件,监控类
    	 */
    	public static  SqlSession Builder(Class classFile)throws Exception {
    		
    		//1.创建被监控实例对象
    		 SqlSession obj=  (SqlSession) classFile.newInstance();
    		//2.创建一个通知对象
    		 InvocationHandler adviser= new Invaction(obj);
    		 //3.向JVM申请负责监控obj对象指定行为的监控对象(代理对象)
    		 /*
    		  *  loader:被监控对象隶属的类文件在内存中真实地址
    		  *  interfaces:被监控对象隶属的类文件实现接口
    		  *  h:监控对象发现小明要执行被监控行为,应该有哪一个通知对象进行辅助
    		  */
    		 SqlSession $proxy= (SqlSession) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);
    	     return $proxy;
    	}
    
    }

    测试:

    public static void main(String[] args) throws Exception {
    	   
    		Map StatementMapper = new HashMap();
    	    StatementMapper.put("dept.save", "insert into dept values(50,'TEST','BEIJING',1)");
    		
    		SqlSession dao =   SqlSessionFactory.Builder(DeptMapper.class);	    	    
    		dao.save((String)StatementMapper.get("dept.save"));
    }

    这样,模拟mybatis的这种动态代理的实现就完成了

  • 相关阅读:
    select应用于read函数 超时非阻塞方式
    取文本索引所执向的值(简单)
    linux c函数指针的应用
    解决vsftp无法启动问题(转)
    Could not chdir to home directory /home/USER: Permission denied
    sscanf和正则表达式
    存储过程重置SEQUENCE值从新开始。
    Signal ()函数详细介绍 Linux函数(转)
    linux 环境NTP配置与开机自启动(转)
    linux下iconv()函数的用法(转载并修改)
  • 原文地址:https://www.cnblogs.com/dulinan/p/12033033.html
Copyright © 2011-2022 走看看