关于代理模式的学习总结
代理模式:就是一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象(即代理对象),以便向外界提供功能接口。
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,
代理模式的作用 将主要业务与次要业务进行松耦合组装
本质:监控行为特征
通俗解释:就是我想买一瓶可乐,最直接的办法就是去商店买一瓶,最复杂或者是最费劲的办法就是去美国可口可乐公司总部去买。
代理模式:就是可口可乐公司给商店一个合法的代理权,让商店帮可口可乐公司代卖可口可乐。我直接去商店买就行了。
JDK代理模式实现
1 接口角色: 定义所有需要被监听行为
2.接口实现类
3.通知类: 1)次要业务进行具体实现
2)通知JVM,当前被拦截的主要业务方法与次要业务方法应该如何绑定执行
4.监控对象(代理对象)
1) 被监控实例对象 2) 需要被监控监控行为 3)具体通知类实例对象
代理模式的代码解读:
1、InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口。任何一个代理类都必须要实现该接口,重写里面的invoke方法
2、编写一个接口类,一个接口实现类如:
2.1接口类
public interface SqlSession {
public int save(String sql)throws Exception;
}
2.2接口实现类
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、编写一个代理类,必须实现InvocationHandler接口,重写invoke()
public class Invaction implements InvocationHandler {
private SqlSession obj;//具体被监控对象(一般都是父类对象,它表示的是一类,实现SqlSession的均是其中某一个具体的体现。所以,监控对象一般都是代表一个大类)
Connection connection ;
PreparedStatement pStatement;
//构造器必须要的
public Invaction(SqlSession param){
this.obj =param;
}
/*
*
* invoke方法:在被监控行为将要执行时,会被JVM拦截
* 被监控行为和行为实现方会被作为参数输送invoke
* ****通知JVM,这个被拦截方法是如何与当前次要业务方法绑定实现
* invoke方法三个参数
*
* proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0
* method:我们所要调用某个对象真实的方法的Method对象
* args:指代代理对象方法传递的参数
*
*
*/
@Override
public Object invoke(Object porxy, Method method, Object[] params) throws Throwable {
Object value;
//1.执行JDBC初始次要业务
init();
//2.执行JDBC主要业务
//还有getFields()和getDeclaredFields(),返回的都是Field对象,获取名称直接field.getName(),
// 但是属性值则是field.get(Object),这个object是该field所属的!!!
Field psField = obj.getClass().getDeclaredField("ps");
//设置overwrite=true,使之没有访问限制,必须要设置的
psField.setAccessible(true);
//将指定对象变量上此 Field 对象表示的字段设置为指定的新值.
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/kaikeba", "root", "root");
pStatement = connection.prepareStatement("");
}
private void close() throws SQLException{
if(pStatement!=null){
pStatement.close();
}
if(connection!=null){
connection.close();
}
}
4、Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但是我们最常用的是newProxyInstance方法。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
5、使用方法
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 class TestMain {
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"));
}
}
相关文章链接