美文网首页
Java代理模式

Java代理模式

作者: 流云飞鸟 | 来源:发表于2017-10-29 20:03 被阅读16次
    什么是代理模式:

    代理模式是23种设计模式中的一种,其思想是:为目标对象提供代理,外部想要访问目标对象就必须通过代理,这样做的意义在于隔离目标对象,比如 明星跟经纪人,就是很典型的代理模式,明星就是目标,经纪人就是代理,现在有一家公司想要找明星拍广告,怎么办,能直接找这个明星吗,不能,那就去找他的代理(经纪人)吧,具体经纪人如何跟明星商量的,广告公司不用管。画个图:


    代理模式.png
    三种代理模式:

    1. 静态代理:
    首先我们定义一个目标对象和代理对象的公共接口(保证在使用者看来,貌似我就是调用了目标对象的方法)

    public interface IStart {
        void advertising();
    }
    

    接下来,我们定义一个目标类

    public class Star implements IStart {
        String name;
    
        public Star(String name) {
            super();
            this.name = name;
        }
    
        // 拍广告
        @Override
        public void advertising() {
            System.out.println("我是" + name + ",我给你拍霸王洗发水的广告");
        }
    }
    

    代理类:

    public class StarProxy implements IStart {
        //我是代理类,我在创建的时候就要给我指定,我要代理谁
        private Star star;
        public StarProxy(Star star) {
            super();
            this.star = star;
        }
    
        @Override
        public void advertising() {
            star.advertising();
        }
    }
    

    好了,所有类都定义好了,我们开始使用

    public static void main(String[] args) {
            Star star = new Star("成龙");
            StarProxy proxy = new StarProxy(star);
            //拍广告
            proxy.advertising();
        }
    
    

    输出结果:我是成龙,我给你拍霸王洗发水广告,是不是很简单呢,对于使用者来说,我调用的是代理对象的方法,但是真正做事的还是目标对象
    大家有没有发现,我的代理类和目标类都实现了同一个接口,IStar,那么如果我现在有新的功能来了,比如,我不仅拍广告,我还可以拍电影,我还可以唱歌,如果添加,那么目标类和代理类都需要维护,这就麻烦了,没关系,下面我们看看动态代理


    2. 动态代理
    动态代理的代理对象不需要实现接口,动态代理的核心类:java.lang.reflect.Proxy,代理对象的生成一般通过
    newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法来生成的,需要三个参数:

    1. ClassLoader 目标对象的类加载器
    2. interfaces[] 目标对象所实现的所有接口,可以是一个也可以是多个
    3. InvocationHandler 事件处理的方法(android中的handler有点像,反正只要知道,他是处理事件的,下文会有代码)
      我们直接上代码,Star和IStar都不用换,创建StarProxy2
    public class StarProxy2 {
        Star star;
    
        public StarProxy2(Star star) {
            super();
            this.star = star;
        }
        public Object getProxy(){
            return Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() {
                
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    //下面代码invoke(),是不是很熟悉,没错,就是反射
                    Object returnObj = method.invoke(star, args);
                    return returnObj;
                }
            });
            
        }
    }
    
    public static void main(String[] args) {
            Star star = new Star("成龙");
            StarProxy2 proxy2 = new StarProxy2(star);
            IStart iStart = (IStart) proxy2.getProxy();
            iStart.advertising();
        }
    

    动态代理和静态代理的区别是,动态代理中,代理类不用实现接口,共同点是目标类需要实现接口,那么有没有目标类和代理类都不用实现接口的代理方式呢,有!哈哈,这就是我们接下来要说的,Cglib代理


    3. Cglib代理(这里仅介绍用法)先去github下载Cglib,他还要依赖asm和ant所以都要分别下载

    Cglib又叫子类代理,为什么呢,其原理就是在内存中创建目标对象的子类作为代理类。他的用途很广泛,例如 Spring AOP。

    //新建一个类,我这里叫StarProxy3,实现MethodInterceptor,这个接口就是来处理代理的方法
    public class StarProxy3 implements MethodInterceptor{
        Star star;
    
        public StarProxy3(Star star) {
            super();
            this.star = star;
        }
        public Object getProxy(){
            //这是一个工具,我们告诉他目标对象的Class,因为一会他要给他创建一个子类
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(star.getClass());
            //这里是设置回掉接口,就是我们实现MethodInterceptor的方法intercept;
            enhancer.setCallback(this);
            //开始创建代理类了
            return enhancer.create();
            
        }
        @Override
        public Object intercept(Object obj, Method method, Object[] args,
                MethodProxy proxy) throws Throwable {
             //通过反射调用,和动态代理一样
            Object returnObj = method.invoke(star, args);
            return returnObj;
        }
    }
    
    
    public static void main(String[] args) {
            Star star = new Star("成龙");
            //这里的proStar实际是Star类的子类
            Star proStar = (Star) new StarProxy3(star).getProxy();
            proStar.advertising();
            
            
        }
    

    注:这里有一个小细节,被代理的类一定要保证有空参构造,因为Cglib代理就是通过目标类的空参构造来创造其子类,并为其代理,若没有,则会报错

    总结:三种代理方式,做android开发一般Cglib用的不多(我是这样子的,因为比较麻烦),一般第二种就完全搞定了,想研究Cglib源码的童鞋可以点这里

    相关文章

      网友评论

          本文标题:Java代理模式

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