Java代理模式

代理模式,顾名思义就是给一个类找个代理,让这个代理类去做一些事情,比如某明星要开演唱会,在开演唱会之前要布置场景,在开演唱会之后要收拾东西,这些事情明星是不需要做的,交给它的代理去做。

在Java中也会有这样的代理类,Java中的代理模式有三种,静态代理,JDK动态代理,GCLib代理

静态代理

所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和目标类的关系在运行前就确定了

使用静态代理的条件是:目标对象(要被代理的对象)和代理对象需要实现相同的接口或者是继承相同父类

定义共同接口

public interface TargetInterFace {
    void save();
}

定义目标类并实现接口

public class Target implements TargetInterFace {
    @Override
    public void save() {
        System.out.println("Target 中的save 执行了");
    }
}

定义代理类并实现接口

public class TargetStaticProxy implements TargetInterFace{
    //注意 这个地方要注入目标类的接口,以实现不同类的执行
    private TargetInterFace targetInterFace;
    public TargetStaticProxy(TargetInterFace targetInterFace ){
        this.targetInterFace = targetInterFace;
    }

    @Override
    public void save() {
        System.out.println("目标方法执行之前的逻辑");
        targetInterFace.save();
        System.out.println("目标方法执行之后的逻辑");
    }
}

测试类

public class ProxyTest {
    public static void main(String[] args) {
        //创建目标对象
        Target target = new Target();
        //创建代理类,并把目标对象交给代理类去代理
        TargetStaticProxy targetStaticProxy = new TargetStaticProxy(target);
        //通过执行代理的方法 从而去执行目标方法
        //执行结果 
        //目标方法执行之前的逻辑
        //Target 中的save 执行了
        //目标方法执行之后的逻辑
        targetStaticProxy.save();
    }
}

从这个小例子可以看出,静态代理使用有限制, 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护

JDK动态代理

动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件

使用条件,目标类同样需要实现接口,代理类则不需要实现接口,而且代理类是由JVM动态的在内存中构建代理对象

目标类不变

public class Target implements TargetInterFace {
    @Override
    public void save() {
        System.out.println("Target 中的save 执行了");
    }
}

代理类

public class TargetDynamicProxy {
    //注意 这个地方要注入目标类的接口,以实现不同类的执行
    private TargetInterFace targetInterFace;
    // 这里定义一个接口,这个接口里面定义一些代理类的执行逻辑
    private Advice advice;

    public TargetDynamicProxy(TargetInterFace targetInterFace,Advice advice) {
        this.targetInterFace = targetInterFace;
        this.advice = advice;
    }

    public Object getProxyInstance() {
        //创建代理类对象
        Object proxyInstance = Proxy.newProxyInstance(
                targetInterFace.getClass().getClassLoader(),//类加载器
                targetInterFace.getClass().getInterfaces(),//目标类实现接口
                new MyInvocationHandler()//事件处理器
        );
        return proxyInstance;
    }

    class MyInvocationHandler implements InvocationHandler {
        /**
         * Processes a method invocation on a proxy instance and returns the result.
         * This method will be invoked on an invocation handler when a method is invoked
         * on a proxy instance that it is  associated with.
         * 处理代理对象上的方法调用并返回结果。当在与之关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
         * 每次代理对象调用方法都会执行这个回调
         *
         * 回调函数
         * @param proxy 代理类
         * @param method 被代理的方法
         * @param args 被代理方法的参数数组
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//            System.out.println("目标调用之前");替换成advice
            advice.beforeMethod();
            //执行目标对象方法,返回方法的返回值
            Object invoke = method.invoke(targetInterFace, args);
//          System.out.println("目标调用之后"); 替换成advice
            advice.afterMethod();
            return invoke;
        }
    }
}

添加一个切面类,里面封装执行逻辑,也就是spring AOP 的原理模拟

public interface Advice {
    void beforeMethod();
    void afterMethod();
}

测试类

public class ProxyTest {
    public static void main(String[] args) {
        //创建目标对象
        Target target = new Target();
        //创建切面类
        Advice advice = new Advice() {
            @Override
            public void beforeMethod() {
                System.out.println("我是动态代理  目标方法执行前");
            }

            @Override
            public void afterMethod() {
                System.out.println("我是动态代理  目标方法执行后");
            }
        };
        //创建代理类,并把目标对象交给代理类去代理
        TargetDynamicProxy dynamicProxy = new TargetDynamicProxy(target, advice);
        TargetInterFace proxyInstance = (TargetInterFace) dynamicProxy.getProxyInstance();
        //执行结果 
        //我是动态代理  目标方法执行前
        //Target 中的save 执行了
        //我是动态代理  目标方法执行后
        proxyInstance.save();
    }
}

Gclib代理

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。

使用条件:目标类和代理类都可以不用实现接口,目标类不能是final的,目标对象的代理方法也不能是final或static,需要引入GCLIb.jar

目标类

public class Person {
    public void speak() {
        System.out.println("目标类说话。。。。");
    }
}

代理类

public class GclibProxy implements MethodInterceptor {
    private Person person;
    private Advice advice;

    public GclibProxy(Person person, Advice advice) {
        this.person = person;
        this.advice = advice;
    }

    /**
     * 通过GCLib实现
     *
     * @return
     */
    public Object getGCLibProxyInstance() {
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置目标父类
        en.setSuperclass(person.getClass());
        //3.设置回调函数 intercept
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }

    @Override
    public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        advice.beforeMethod();
        //执行目标对象的方法
        Object o = method.invoke(target, objects);
        advice.afterMethod();
        return o;
    }
}

测试类

public class ProxyTest {
    public static void main(String[] args) {
        //创建目标对象
        Target target = new Target();
        //创建切面类
        Advice advice = new Advice() {
            @Override
            public void beforeMethod() {
                System.out.println("我是动态代理  目标方法执行前");
            }

            @Override
            public void afterMethod() {
                System.out.println("我是动态代理  目标方法执行后");
            }
        };
        //创建代理类,并把目标对象交给代理类去代理
        TargetDynamicProxy dynamicProxy = new TargetDynamicProxy(target, advice);
        TargetInterFace proxyInstance = (TargetInterFace) dynamicProxy.getProxyInstance();
        //执行结果
        //我是动态代理  目标方法执行前
        //Target 中的save 执行了
        //我是动态代理  目标方法执行后
//        proxyInstance.save();


        //
        Person person = new Person();
        GclibProxy gclibProxy = new GclibProxy(person, advice);
        Person personProxyInstance = (Person) gclibProxy.getGCLibProxyInstance();
        personProxyInstance.speak();

    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值