红橙Darren视频笔记 代理模式 动态代理和静态代理

红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25)

关于代理模式我之前有过相关的介绍:
https://blog.csdn.net/u011109881/article/details/82848719
里面介绍了各种代理模式使用的情况

静态代理demo

接口类

public interface IBank {
    // 申请银行卡
    void applyBank();
    
    // 挂失
    void loseBank();
}

代理类

// 银行业务员 代理类
public class BusinessMan implements IBank{

    private final IBank mConsumer;

    public BusinessMan(IBank man){
        this.mConsumer = man;
    }

    @Override
    public void applyBank() {
    	//申请银行卡
    	if(mConsumer != null){
            Log.e("hjcai","进行挂号等基础流程");
            mConsumer.applyBank();
            Log.e("hjcai","流程结束");
    	}
    }
    // 申请挂失
	@Override
	public void loseBank() {
        if (mConsumer != null){
            Log.e("hjcai","进行挂号等基础流程");
            mConsumer.loseBank();
            Log.e("hjcai","流程结束");
        }
	}
}

被代理类

// 消费者
public class Consumer implements IBank{

    @Override
    public void applyBank() {
        Log.e("hjcai","申请新的银行卡");
    }

	@Override
	public void loseBank() {
        Log.e("hjcai","申请挂失");
	}
	
	// ......
}

动态代理demo

接口类

public interface IBank {
    // 申请银行卡
    void applyBank();
    
    // 挂失
    void loseBank();
}

代理类
实际上动态代理不需要创建代理类 但是需要创建一个继承自InvocationHandler的代理类方法被调用时的CallBack

/**
 * {@code InvocationHandler} is the interface implemented by
 * the <i>invocation handler</i> of a proxy instance.
 *
 * InvocationHandler是一个接口 该接口被invocation handler的代理实例实现
 *
 * <p>Each proxy instance has an associated invocation handler.
 * When a method is invoked on a proxy instance, the method
 * invocation is encoded and dispatched to the {@code invoke}
 * method of its invocation handler.
 *
 * 每个代理实例有一个相关联的调用handler
 * 当代理实例的一个方法被调用时 该方法的调用会被编码并分发给他的invocation handler的invoke方法
 *
 * @author      Peter Jones
 * @see         Proxy
 * @since       1.3
 */
public class DynamicProxyCallBack implements InvocationHandler {

    private final IBank mConsumer;

    public DynamicProxyCallBack(IBank consumer) {
        this.mConsumer = consumer;
    }


    /**
     * 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 对应方法的参数
     *
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.e("hjcai","做一些挂号等基础流程");
        Object object = method.invoke(mConsumer, args);
        Log.e("hjcai","流程结束");
        return object;
    }
}

被代理类

// 消费者
public class Consumer implements IBank{

    @Override
    public void applyBank() {
        Log.e("hjcai","申请新的银行卡");
    }

	@Override
	public void loseBank() {
        Log.e("hjcai","申请挂失");
	}
	
	// ......
}

测试类(静态与动态代理demo共用)

public class MainActivity extends AppCompatActivity {

    BusinessMan mBusinessMan;// 静态代理对象
    IBank mConsumerProxy;// 动态代理对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 被代理对象
        Consumer mConsumer = new Consumer();
        
        // 静态代理对象
        mBusinessMan = new BusinessMan(mConsumer);

        // 动态代理对象
        mConsumerProxy = (IBank) Proxy.newProxyInstance(
                mConsumer.getClass().getClassLoader(),
                mConsumer.getClass().getInterfaces(),
                new DynamicProxyCallBack(mConsumer));
    }

    // 静态代理测试
    public void staticApply(View view) {
        // 调用的代理类的方法 但是核心内容调用的是真实类(消费者)的方法
        mBusinessMan.applyBank();
    }

    // 静态代理测试
    public void staticLose(View view) {
        // 调用的代理类的方法 但是核心内容调用的是真实类(消费者)的方法
        mBusinessMan.loseBank();
    }

    // 动态代理测试
    public void dynamicLose(View view) {
        mConsumerProxy.loseBank();
    }

    // 动态代理测试
    public void dynamicApply(View view) {
        mConsumerProxy.applyBank();
    }
}

不管是静态代理还是动态代理 他们的结构都是 代理的接口+被代理类+代理类+测试类
可以看到动态代理与静态代理前两部分完全一致 少数不同的地方
1.代理对象的生成方式
2.代理方法调用时的处理方式不一样

Java动态代理生成方法newProxyInstance的源码浅析

这里选用的是API25的Proxy源码 因为到26的时候 源码已经发生了巨大的变化 其中有个proxyClassCache变量 完全不知道内部是如何操作的 只能看看API25的源码了
大致思路
调用Java的代理类生成方法生成一个代理类
代理类调用方法的时候 invoke方法被调用 并且知道调用的方法和参数
需要知道为什么 代理类调用方法的时候 invoke方法是如何调用的

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
    	// 判空
        if (h == null) {
            throw new NullPointerException();
        }

        /*
         * Look up or generate the designated proxy class.
         */
         // 获取代理类的Class 用于反射生成代理类
        Class<?> cl = getProxyClass0(loader, interfaces);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
        	// 根据class+参数得到对应的构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            // 将handler作为参数传进创建Instance的方法 newInstance方法后继续跟进 发现最终调用的是native方法
            // 但是我们可以猜测 该对象将handler作为内部变量 当调用代理对象的方法的时候 通过handler通知外部方法被调用
            return newInstance(cons, h);
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        }
    }
    
	// 获取代理类的Class类型
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        // 判断接口数目合法性
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // 声明返回的Class类型对象
        Class<?> proxyClass = null;

        /* collect interface names to use as key for proxy class cache */
        // 所有接口的名称集合
        String[] interfaceNames = new String[interfaces.length];

        // 利用interfaceNames+interfaceSet进行接口名称的去重 已经接口合法性检测
        // for detecting duplicates
        Set<Class<?>> interfaceSet = new HashSet<>();

        for (int i = 0; i < interfaces.length; i++) {
            /*
             * Verify that the class loader resolves the name of this
             * interface to the same Class object.
             */
            String interfaceName = interfaces[i].getName();
            Class<?> interfaceClass = null;
            try {
                interfaceClass = Class.forName(interfaceName, false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != interfaces[i]) {
                throw new IllegalArgumentException(
                    interfaces[i] + " is not visible from class loader");
            }

            /*
             * Verify that the Class object actually represents an
             * interface.
             */
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }

            /*
             * Verify that this interface is not a duplicate.
             */
            if (interfaceSet.contains(interfaceClass)) {
                throw new IllegalArgumentException(
                    "repeated interface: " + interfaceClass.getName());
            }
            interfaceSet.add(interfaceClass);

            interfaceNames[i] = interfaceName;
        }

        /*
         * Using string representations of the proxy interfaces as
         * keys in the proxy class cache (instead of their Class
         * objects) is sufficient because we require the proxy
         * interfaces to be resolvable by name through the supplied
         * class loader, and it has the advantage that using a string
         * representation of a class makes for an implicit weak
         * reference to the class.
         */
        // 使用string(而不是类对象)在代理类的缓存中作为key代表代理接口已经足够
        // 因为 我们需要代理接口可以根据提供的class loader按照名字来区别 
        // 并且使用string还有一个优势 即 使用string代表一个class作为与该类真正的Class关联弱引用的一个key
        List<String> key = Arrays.asList(interfaceNames);

        /*
         * Find or create the proxy class cache for the class loader.
         */
        // 做一个缓存
        Map<List<String>, Object> cache;
        synchronized (loaderToCache) {
            cache = loaderToCache.get(loader);
            if (cache == null) {
                cache = new HashMap<>();
                loaderToCache.put(loader, cache);
            }
            /*
             * This mapping will remain valid for the duration of this
             * method, without further synchronization, because the mapping
             * will only be removed if the class loader becomes unreachable.
             */
        }

        /*
         * Look up the list of interfaces in the proxy class cache using
         * the key.  This lookup will result in one of three possible
         * kinds of values:
         *     null, if there is currently no proxy class for the list of
         *         interfaces in the class loader,
         *     the pendingGenerationMarker object, if a proxy class for the
         *         list of interfaces is currently being generated,
         *     or a weak reference to a Class object, if a proxy class for
         *         the list of interfaces has already been generated.
         */
        synchronized (cache) {
            /*
             * Note that we need not worry about reaping the cache for
             * entries with cleared weak references because if a proxy class
             * has been garbage collected, its class loader will have been
             * garbage collected as well, so the entire cache will be reaped
             * from the loaderToCache map.
             */
            do {
                Object value = cache.get(key);
                if (value instanceof Reference) {
                    proxyClass = (Class<?>) ((Reference) value).get();
                }
                // 存在缓存
                if (proxyClass != null) {
                    // proxy class already generated: return it
                    return proxyClass;
                } else if (value == pendingGenerationMarker) {
                    // proxy class being generated: wait for it
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {
                        /*
                         * The class generation that we are waiting for should
                         * take a small, bounded time, so we can safely ignore
                         * thread interrupts here.
                         */
                    }
                    continue;
                } else {
                    /*
                     * No proxy class for this list of interfaces has been
                     * generated or is being generated, so we will go and
                     * generate it now.  Mark it as pending generation.
                     */
                    cache.put(key, pendingGenerationMarker);
                    break;
                }
            } while (true);
        }
        // 上面有些不明白 初次初始化的时候怎么终结上面的死循环???

        try {
            // 准备获取代理对象包名
            String proxyPkg = null;     // package to define proxy class in

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            for (int i = 0; i < interfaces.length; i++) {
                int flags = interfaces[i].getModifiers();
                if (!Modifier.isPublic(flags)) {// 跳过非public的接口
                    String name = interfaces[i].getName();
                    // 取得最后一个点
                    int n = name.lastIndexOf('.');
                    // 最后一个点之前的部分是包名
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // 没有非公开接口的代理接口的包名 使用空包名
                // if no non-public proxy interfaces, use the default package.
                proxyPkg = "";
            }

            {
                // Android-changed: Generate the proxy directly instead of calling
                // through to ProxyGenerator.
                // 获取接口的所有方法
                List<Method> methods = getMethods(interfaces);
                // 排序
                Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
                // 确认返回类型
                validateReturnTypes(methods);
                // 查看是否抛出异常
                List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);

                // 转换为数组
                Method[] methodsArray = methods.toArray(new Method[methods.size()]);
                // 异常改变为二维数组
                Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);

                /*
                 * Choose a name for the proxy class to generate.
                 */
                final long num;
                synchronized (nextUniqueNumberLock) {
                    num = nextUniqueNumber++;
                }
                // 代理类的名称:
                // 包名+前缀($Proxy)+当前实例在多线程中的index
                String proxyName = proxyPkg + proxyClassNamePrefix + num;

                // 调用native方法 得到代理对象的class
                proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,
                        exceptionsArray);
            }
            // add to set of all generated proxy classes, for isProxyClass
            proxyClasses.put(proxyClass, null);

        } finally {
            /*
             * We must clean up the "pending generation" state of the proxy
             * class cache entry somehow.  If a proxy class was successfully
             * generated, store it in the cache (with a weak reference);
             * otherwise, remove the reserved entry.  In all cases, notify
             * all waiters on reserved entries in this cache.
             */
            synchronized (cache) {
                if (proxyClass != null) {
                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
                } else {
                    cache.remove(key);
                }
                cache.notifyAll();
            }
        }
        // 返回代理对象的class 继续查看newProxyInstance方法
        return proxyClass;
    }

	private final static String proxyClassNamePrefix = "$Proxy";
    private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
                                                 ClassLoader loader, Method[] methods,
                                                 Class<?>[][] exceptions);

    private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
        try {
            return cons.newInstance(new Object[] {h} );
        } catch (IllegalAccessException | InstantiationException e) {
            throw new InternalError(e.toString());
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString());
            }
        }
    }

    public T newInstance(Object... args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (serializationClass == null) {
            // newInstance0 newInstanceFromSerialization都是native方法
            return newInstance0(args);
        } else {
            return (T) newInstanceFromSerialization(serializationCtor, serializationClass);
        }
    }

    private static native Object newInstanceFromSerialization(Class<?> ctorClass, Class<?> allocClass)
        throws InstantiationException, IllegalArgumentException, InvocationTargetException;

    private native T newInstance0(Object... args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException;

总结动态代理
1.解析interface所有方法
2.新建一个class,class的name: 包名+$Proxy+所处线程index,
3.通过native实例化代理proxy对象,proxy的里面包含InvocationHandler
4.每次调代理类方法会通知InvocationHandler里面的invoke方法 并告知调用了什么方法传递的什么参数等信息
第四步中很多信息其实隐藏在c++层 这里只是猜测
相比于静态代理,动态代理不需要我们自己创建代理类 并且我们可以在方法调用的前后做统一的处理,但是如果我们在各个方法前后需要进行不一样的处理 那么这个时候就更应该选择静态代理了吧?
最后想到一个可以用静态代理模拟动态代理的方法 不过相比于真正的动态代理的灵活性 还是有不少差距

    @Override
    public void applyBank() {
        //申请银行卡
        if (mConsumer != null) {
            beforeOperation();
            mConsumer.applyBank();
            afterOperation();
        }
    }
    
    private void beforeOperation(){
        Log.e("hjcai", "beforeOperation");
    }

    private void afterOperation(){
        Log.e("hjcai", "afterOperation");
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值