美文网首页
代理模式

代理模式

作者: Hey_Shaw | 来源:发表于2018-02-23 20:23 被阅读3次

    静态代理

    大学室友四喜要结婚了,邀请了室友三宝和五福。得到通知怎么办,都需要准备红包啊。既然都需要(虽然都是红包,可能份额不一样),好的,定义一个红包的接口:

    /**
     *  创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法
     *  @author Hey Shaw <br>
     *  2018年2月12日上午10:25:58
     */
    public interface RedEnvelopesInterface {
        
        void slippingSomeoneMoney() ;
        
    }
    

    三宝塞了600进去了

    /**
     * 创建一个代理类,同时使其也实现RedEnvelopesInterface 这个接口
     * @author Hey Shaw<br>
     * 2018年2月12日上午10:29:13
     */
    public class SanbaoRedEnvelopes implements RedEnvelopesInterface {
    
        @Override
        public void slippingSomeoneMoney() {
            // TODO Auto-generated method stub
            System.out.println("三宝的红包,688块钱!");
        }
    
    }
    

    三宝红包准备好了,可是忽然当天有事去不了,这时他想起了让五福帮他顺带一下:

    /**
     * 代理类实现和被代理类相同的方法,也就是被代理类的任务让代理类顺带完成!
     * @author Hey Shaw<br>
     * 2018年2月12日上午11:50:52
     */
    public class WufuRedEnvelopesStaticsProxy implements RedEnvelopesInterface{
        
        /**
         *  拿到三宝的红包 (代理类中持有一个被代理对象的引用)
         */
        private RedEnvelopesInterface redEnvelopesInterface = new SanbaoRedEnvelopes() ;
        
        /** 上面的代码可以优化成:
        private RedEnvelopesInterface redEnvelopesInterface ;
            
        public WufuRedEnvelopesStaticsProxy (RedEnvelopesInterface redEnvelopesInterface){  
            this.redEnvelopesInterface  = redEnvelopesInterface ;
         }
        **/
        /**
         * 在代理类方法中调用该对象的方法
         */
        @Override
        public void slippingSomeoneMoney() {
            // TODO Auto-generated method stub
            System.out.println("五福的红包,666块钱 !");
            redEnvelopesInterface.slippingSomeoneMoney();
            System.out.println("带上自己和三宝的红包出发!");
        }
    
    }
    

    将红包交给四喜:

    public class LeaveRedEnvelopesToSixi{
        
        public static void main(String[] args) {
            // 静态代理
            WufuRedEnvelopesStaticsProxy redEnvelopesProxy = new WufuRedEnvelopesStaticsProxy();
            /* 优化后调用
            WufuRedEnvelopesStaticsProxy redEnvelopesProxy = new WufuRedEnvelopesStaticsProxy(new SanbaoRedEnvelopes());
            */
            redEnvelopesProxy.slippingSomeoneMoney();
        }
        
    }
    

    动态代理

    突遇状况,五福零时有事,也去不了了;这时候三宝想到通过支付宝红包,好了,仍然需要先装好红包,再发给四喜。

    沿用:
    Interface RedEnvelopesInterface
    Class SanbaoRedEnvelopes

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * JDK动态代理(相当于一个代理机构,可以接受很多不同的代理任务)
     * @author Hey Shaw<br>
     * 2018年2月12日上午10:36:06
     */
    public class AlipayDynamicPeoxy implements InvocationHandler {
        
        private Object subject ;   // 任意所需代理的任务
        
        public AlipayDynamicPeoxy(Object subject) {
            this.subject = subject ;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("Before invoke " + method.getName());
            method.invoke(subject, args);
            System.out.println("After invoke " + method.getName());
            return null;
        }
    
    }
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class LeaveRedEnvelopesToSixi{
        
        public static void main(String[] args) {
            // 动态代理
            SanbaoRedEnvelopes sanbaoRedEnvelopes = new SanbaoRedEnvelopes();
            InvocationHandler invocationHandler = new AlipayDynamicPeoxy(sanbaoRedEnvelopes) ;
            
            RedEnvelopesInterface redEnvelopesInterface= (RedEnvelopesInterface) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),
                  sanbaoRedEnvelopes.getClass().getInterfaces(), invocationHandler);
            redEnvelopesInterface.slippingSomeoneMoney();
        }
        
    }
    

    静态代理其实不一定需要接口,代理-只需要将三宝需要完成的事代完成即可;JDK动态代理则需要通过接口来实现动态的指定执行哪个代理任务。

    一个红包需要封装一个接口,如果在需要给四喜捎点特产,有需要封装一个接口,调用时有需要指向不同的实例,代码量太大。这是就有了CGlib动态代理。

    发了一个红包还需要四喜领取才能到账,三宝决定直接转账,直截了当。

    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    /**
     *  用于创建增强代理实现了方法拦截
     *  在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,
     * @author Hey Shaw<br>
     * 2018年2月22日上午11:50:19
     */
    public class RedEnvelopesMethodInterceptor implements MethodInterceptor {
        
        /**
         *  Object为由CGLib动态生成的代理类实例
         *  Method为上文中实体类所调用的被代理的方法引用
         *  Object[]为参数值列表
         *  MethodProxy为生成的代理类对方法的代理引用
         *  return :从代理实例的方法调用返回的值
         */
            @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("Before:"+method.getName());
            Object object = methodProxy.invokeSuper(o, objects); // 调用代理示例方法
            System.out.println("After:"+method.getName());
            return object;
        }
    
    }
    
    import net.sf.cglib.proxy.Enhancer;
    
    public class LeaveRedEnvelopesToSixi{
        
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer() ;    // CGLIB的字节码增强器
            enhancer.setSuperclass(SanbaoRedEnvelopes.class);  //  继承被代理类
            enhancer.setCallback(new RedEnvelopesMethodInterceptor ());  // 生成代理类对象
            SanbaoRedEnvelopes sanbaoRedEnvelopes= (SanbaoRedEnvelopes) enhancer.create() ;   // 在调用代理类中方法是会被我们实现的方法拦截器进行拦截
            System.out.println("调用时进行方法拦截。。。");
            sanbaoRedEnvelopes.slippingSomeoneMoney();
        }
        
    }
    

    相关文章

      网友评论

          本文标题:代理模式

          本文链接:https://www.haomeiwen.com/subject/pnaatftx.html