美文网首页
反射机制和代理模式

反射机制和代理模式

作者: yunqing_71 | 来源:发表于2019-10-12 16:40 被阅读0次

静态代理

package com.macro.mall.test;

/**
 * 静态代理
 */
public class StaticProxy {

    public static void main(String[] args) {
        //创建一个代理对象
        ICarFactory iCarFactory = new CarProxy();
        //代理对象调用sellCar方法,而在代理对象的sellCar方法中则调用了生产厂商的卖车服务向用户提供了汽车
        iCarFactory.sellCar();
    }

}

/**
 * 一个卖车的功能抽象成接口
 */
interface ICarFactory {
    public void sellCar();
}

/**
 * 车辆厂家,实现卖车的接口
 */
class CarFactory implements ICarFactory {

    @Override
    public void sellCar() {
        System.out.println("我是车辆厂家,这是我对卖车接口的实现");
    }
}

/**
 * 这是一个车辆的代理商,也实现了卖车的接口
 */
class CarProxy implements ICarFactory {

    //最后提供卖车服务的目标对象
    private ICarFactory target;
    @Override
    public void sellCar() {

        if (target == null) {//如果没初始化,new一下车辆的生产厂商
            target = new CarFactory();
        }
        target.sellCar();//调用生产厂商的卖车实现

    }
}

静态代理中三个角色的含义:

1.抽象角色: 真实角色和代理角色的共同接口,上述例子中的ICarFactory ,汽车生产厂商和代理厂商都需要实现该接口并实现接口中的方法。
2.真是角色: 最重要引用的对象,上述例子中的厂商实现类CarFatory,会提供真是的服务。
3.代理角色:内部含有真实对象的引用,从而可以操作真实对象,上述例子中的代理商类CarProxy,在其中引入真实角色,并且调用真实角色中的方法向用户提供服务。

动态代理

package com.macro.mall.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy {

    public static void main(String[] args) {
        /**
         * 要被代理的真实对象
         */
        IService iService = new ServiceImpl();
        /**
         * 要代理那个真实对象就输入进去这个真实对象
         *
         */
        InvocationHandler invocationHandler = new MyInvocationHandler(iService);
        /**
         * 通过第一个参数指定加载代理对象的方法
         * 通过第二个参数指定为代理对象提供服务的接口
         * 通过第三个参数把整个代理对象关联到invocationHandler这个对象上
         */
        IService serviceProxy = (IService) Proxy.newProxyInstance(iService.getClass().getClassLoader(),
                iService.getClass().getInterfaces(), invocationHandler);

        System.out.println(serviceProxy.sellCar("奔驰"));

    }
}

/**
 * 提供卖车服务的接口
 */
interface IService{

    public String sellCar(String carName);
}

/**
 * 实现服务的类
 */
class ServiceImpl implements IService{

    @Override
    public String sellCar(String carName) {
        return carName;
    }
}

/**
 * 实现反射包中的InvocationHandler接口
 */
class MyInvocationHandler implements InvocationHandler {

    private Object target;

    //在构造函数中初始化target对象
    MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("Call:" + method.getName());
        /**
         * 通过method中的invoke方法调用target类中的方法
         * args是参数。是从invoke方法的参数中输入的
         */
        Object obj = method.invoke(target, args);
        return obj;
    }
}

通过上述代码,我们能看到动态代理中确实用到了代理机制,但是我们明明没有在main方法中调用MyInvocationHandler类的invoke方法,但是为什么输出结果显示还是被调用了?
这是因为MyInvocationHandler类实现了InvocationHandler接口,并且把代理对象和invocationHandler关联上了,根据invocationHandler的内部实现机制,如果地阿里类serviceProxy发出调用方法的请求,那么这个请求最终会在invoke方法中调用。

那么下一问题:既然serviceProxy也是Iservice类型的那么为什么不直接如下new,而是通过代理来调用?

IService serviceProxy = new ServiceImpl();
serviceProxy.sellCar();

与new方法不同,这里我们把调用控制权交给了InvocationHandler接口的invoke方法,换句话说,在调用sellCar方法时,这个调用请求会先被invoke方法截取,在处理sellCar方法的之前或之后,我们可以添加必要的代码。

例如我们要在sellCar方法之前添加一个选车的方法,在之后添加一个加入车友会的方法,如果不用动态代理,大概代码会如下:

调用选车方法
调用sellCar方法
调用加入车友会方法

如果代码中有100个调用sellCar的方法,那个就要修改100次,每一个的之前之后都加上这两个方法,很难维护,但是如果基于动态代理实现,只需要在invoke方法的这个地方加上两个方法就好了。

/**
 * 实现反射包中的InvocationHandler接口
 */
class MyInvocationHandler implements InvocationHandler {

    private Object target;

    //在构造函数中初始化target对象
    MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("Call:" + method.getName());
        /**
         * 通过method中的invoke方法调用target类中的方法
         * args是参数。是从invoke方法的参数中输入的
         */
        //选车方法
        Object obj = method.invoke(target, args);
        //加入车友会方法
        return obj;
    }
}

总结:与静态代理相比,动态代理的有时就是真实服务里面的所有方法最终都是在InvocationHandler接口的invoke方法里被调用的。一方面,当接口方法数量比较多的时候,可以灵活的通过method.invoke的反射机制来处理,而不需要像静态代理那样定义很多用不上但不得不重写的方法(如果实现了接口,就必须重写方法,不管用不用得到),另一方面,在动态代理的invoke方法中,还可以在调用服务之前或之后等位置加上相关代码,这点静态代理也是无法轻易做到的。

相关文章

  • 反射机制和代理模式

    静态代理 静态代理中三个角色的含义: 1.抽象角色: 真实角色和代理角色的共同接口,上述例子中的ICarFacto...

  • Java反射机制详解(二)

    本篇文章继续介绍Java反射机制,不同的是侧重于介绍动态代理。动态代理是代理模式中的一种,是通过Java反射机制来...

  • Java反射机制总结(二)

    本篇文章继续介绍Java反射机制,不同的是侧重于介绍动态代理。动态代理是代理模式中的一种,是通过Java反射机制来...

  • 动态代理原理及在 Android 中的应用

    一、动态代理简介 1、什么是动态代理? 通过反射机制动态生成代理者对象的一种设计模式。 2、如何区分静态代理和动态...

  • JDK动态代理

    在看这篇文章前,可以先去了解RTTI和反射机制。 1.代理模式 什么是代理模式?例如找房子,我们可以自己找,也可以...

  • Java的反射机制和代理模式

    1.Java反射机制 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用...

  • 掌握java动态代理及原理有多难?

    前言:使用的jdk是1.7,需要了解反射机制 泛型 字节码登概念! 一、代理模式 代理模式是常用的java设计模...

  • 代理模式

    代理模式分静态代理和动态代理,动态代理是依靠反射机制来实现的。在不适合直接对一个原对象操作的时候,就可以用到代理模...

  • 14.动态代理

    代理模式 java动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandle...

  • 代理模式和反射

    1. 静态代理 定义:代理模式给某一对象提供一个代理对象,并由代理对象控制对原对象的引用。 1.1 为什么使用代理...

网友评论

      本文标题:反射机制和代理模式

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