设计模式学习笔记:一、代理模式(动态代理实现)

以数据库查询为例:

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的这种动态代理的实现就完成了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值