代理模式

代理模式

一、概念

代理模式是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,代理模式属于结构型设计模式。使用代理模式主要有两个目的:一保护目标对象,二增强目标对象。

二、JDK动态代理

代理的目标接口,相亲

public interface Person {

    public void findLove();

}

代理目标实现,要相亲的人

public class JDKCustomer implements Person {
    @Override
    public void findLove() {
        System.out.println("高富帅");
        System.out.println("身高180cm");
        System.out.println("胸大,6块腹肌");
    }
}

代理类媒婆,帮客户找对象

public class JDKMeipo implements InvocationHandler {

    private Object target;

    public Object getInstance(Object target) throws Exception{
        this.target=target;

        Class<?> aClass = target.getClass();
        return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        method.invoke(this.target,args);
        after();
        return null;
    }

    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
}

test

public class JDKProxyTest {

    public static void main(String[] args) {
        try{
            Person person = (Person) new JDKMeipo().getInstance(new JDKCustomer());
            person.findLove();

            byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class});
            FileOutputStream fos = new FileOutputStream("E://$Proxy0.class");
            fos.write(bytes);
            fos.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

特点

1.代理的目标必须实现接口,生成的代理类和目标实现同样的接口,有点装饰模式的意思
2.需要提供类加载器,代理目标类的类加载器
3.需要提供一个实现了InvocationHandler接口的类对象(重点是invoke方法)
4.调用目标方式时使用的是反射调用
5.JDK是直接写Class字节码,生成代理类,生成的代理类实现了代理目标的所有接口,并实现了其方法。
6.方法的方法default方法无法被代理,代理目标类的方法如果不是来自接口则无法被代理
7.需要提供代理目标类的实例(对象),内部类似装饰调用,最终执行方法的还是我们提供的对象来完成的。先生成对象,设置参数,再生成代理对象。
8.记住,是接口实现代理,只能代理接口抽象的方法

原理

/**
 * <p>
 *     JDK代理,生成的代理类模拟
 * </p>
 *
 * @author: longWarren
 * @time: 2020/08/31
 */
public class JDKProxyClassSimulation {

    /**
     * <p>
     *     jdk代理特点
     *      1.代理的目标必须实现接口
     *      2.需要提供类加载器,代理目标类的类加载器
     *      3.需要提供一个实现了InvocationHandler接口的类对象(重点是invoke方法)
     *      4.调用目标方式时使用的是反射调用
     *      5.JDK是直接写Class字节码,生成代理类,生成的代理类实现了代理目标的所有接口,并实现了其方法。
     * </p>
     */
    public static class JDKProxyClass extends Proxy implements Person {

        /**
         * 这就是实现代理的核心,proxy中有一个h对象,就是InvocationHandler的实现,真正的掉用就是其invoke方法
         * @param h
         */
        public JDKProxyClass(InvocationHandler h) {
            super(h);
        }
        
        @Override
        public void findLove() {
            try
            {
                super.h.invoke(this, m3, null);
                return;
            }
            catch(Error _ex) { }
            catch(Throwable throwable)
            {
                throw new UndeclaredThrowableException(throwable);
            }
        }

        private static Method m3;
        private static Method m2;
        private static Method m1;
        private static Method m0;

        static
        {
            try
            {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
                        Class.forName("java.lang.Object")
                });
                m3 = Class.forName("com.dalong.learn.design.mode.proxy.Person").getMethod("findLove", new
                        Class[0]);
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            }
            catch(NoSuchMethodException nosuchmethodexception)
            {
                throw new NoSuchMethodError(nosuchmethodexception.getMessage());
            }
            catch(ClassNotFoundException classnotfoundexception)
            {
                throw new NoClassDefFoundError(classnotfoundexception.getMessage());
            }
        }
    }
}

三,CGLIB动态代理

代理的目标接口,相亲

public interface Person {

    public void findLove();

}

代理目标实现,要相亲的人

public class CglibCustomer implements Person {
    @Override
    public void findLove() {
        System.out.println("高富帅");
        System.out.println("身高180cm");
        System.out.println("胸大,6块腹肌");
    }
}

代理类媒婆,帮客户找对象

public class CglibMeipo implements MethodInterceptor {

    public Object getInstance(Class<?> clazz) throws Exception{
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object o1 = methodProxy.invokeSuper(o, objects);
        after();
        return o1;
    }

    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
}

特点

1.代理的目标无需实现接口,生成的代理类会继承要代理的类,所以要代理的类不可以用final修饰
2.需要提供一个实现了MethodInterceptor接口的类对象(重点是intercept方法)
3.使用的是继承方式实现,不能代理final方法
4.调用目标方式时使用的直接调用(super.method()),使用FastClass实现(不太懂里面的细节)
5.无需提供代理目标类的实例(对象),先生成代理对象,再设置参数
6.CGLib 使用ASM框架写Class 字节码,Cglib 代理实现更复杂,生成代理类比JDK 效率低。
7.CGLib 是通过FastClass 机制直接调用方法,CGLib 执行效率更高。

原理

public class CglibProxyClassSimulation {


    public static class CglibProxyClass extends CglibCustomer implements Factory {

        private MethodInterceptor methodInterceptor;

        //使用dialing类调用时,会调用这个方法,然后转入intercept方法
        public final void findLove(){
            //methodInterceptor.intercept();
            return;

        }

        //intercept里面调用 methodProxy.invokeSuper(o, objects);就会调用这个方法
        public void cgLibFindLove(){
            super.findLove();
        }

        @Override
        public Object newInstance(Callback callback) {
            return null;
        }

        @Override
        public Object newInstance(Callback[] callbacks) {
            return null;
        }

        @Override
        public Object newInstance(Class[] classes, Object[] objects, Callback[] callbacks) {
            return null;
        }

        @Override
        public Callback getCallback(int i) {
            return null;
        }

        @Override
        public void setCallback(int i, Callback callback) {
        }

        @Override
        public void setCallbacks(Callback[] callbacks) {

        }

        @Override
        public Callback[] getCallbacks() {
            return new Callback[0];
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值