代理模式学习笔记

关于代理模式的学习总结

    代理模式:就是一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

    在代理模式中,我们创建具有现有对象的对象(即代理对象),以便向外界提供功能接口。
    
    意图:为其他对象提供一种代理以控制对这个对象的访问。

    主要解决:在直接访问对象时带来的问题,
    
    代理模式的作用 将主要业务与次要业务进行松耦合组装
    
    本质:监控行为特征 
    
    通俗解释:就是我想买一瓶可乐,最直接的办法就是去商店买一瓶,最复杂或者是最费劲的办法就是去美国可口可乐公司总部去买。
    
    代理模式:就是可口可乐公司给商店一个合法的代理权,让商店帮可口可乐公司代卖可口可乐。我直接去商店买就行了。
    
    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"));
                }

            }

        

 

相关文章链接

https://blog.csdn.net/yaomingyang/article/details/80981004?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值