代理模式详解

2023-10-26

第一节 代理模式介绍

1. 什么是代理模式

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.

代理模式分为静态代理和动态代理两种

2. 静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同的父类

2.1 案例

使用静态代理完成苹果手机专卖店代理苹果手机批发商卖手机的这一过程

  • 定义接口

    <span style="background-color:#f8f8f8"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
    ​
    <span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">Seller</span> {
        <span style="color:#aa5500">/**</span>
         <span style="color:#aa5500">* 卖手机</span>
         <span style="color:#aa5500">* @param price</span>
         <span style="color:#aa5500">*/</span>
        <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>);
    }</span>
  • 定义苹果手机批发商

    <span style="background-color:#f8f8f8"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
    ​
    <span style="color:#aa5500">/**</span>
     <span style="color:#aa5500">* 苹果手机批发商A</span>
     <span style="color:#aa5500">*/</span>
    <span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneWholesaler</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
    ​
        <span style="color:#555555">@Override</span>
        <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
            <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"苹果手机批发商A卖手机价格为:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">price</span>);
        }
    }</span>
  • 定义苹果手机专卖店

    <span style="background-color:#f8f8f8"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
    ​
    <span style="color:#aa5500">/**</span>
     <span style="color:#aa5500">* 苹果手机专卖店A代理卖苹果手机</span>
     <span style="color:#aa5500">*/</span>
    <span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreA</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
    ​
        <span style="color:#770088">private</span>  <span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>;
    ​
        <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>){
            <span style="color:#770088">this</span>.<span style="color:#000000">wholesaler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">wholesaler</span>;
        }
    ​
        <span style="color:#555555">@Override</span>
        <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
            <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1000</span>;
            <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
            <span style="color:#000000">wholesaler</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#000000">price</span>);
            <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> (<span style="color:#000000">price</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
        }
    }</span>
  • 编写测试案例

    <span style="background-color:#f8f8f8"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
    ​
    <span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreATest</span> {
    ​
        <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#000000">main</span>(<span style="color:#008855">String</span>[] <span style="color:#000000">args</span>) {
            <span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneWholesaler</span>();
            <span style="color:#000000">IPhoneSpecialtyStoreA</span> <span style="color:#000000">specialtyStoreA</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">wholesaler</span>);
            <span style="color:#000000">specialtyStoreA</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#116644">12000</span>);
        }
    }</span>

结论: 静态代理可以在不改变原有功能的基础上,对功能进行增强。

2.2 静态代理引发的问题

假如现在又有一家专卖店准备代理售卖苹果手机,那么会出现如下的编码

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店A代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreB</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span>  <span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>;
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreB</span>(<span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>){
        <span style="color:#770088">this</span>.<span style="color:#000000">wholesaler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">wholesaler</span>;
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1200</span>;
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
        <span style="color:#000000">wholesaler</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#000000">price</span>);
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> (<span style="color:#000000">price</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
    }
}</span></span>

如果有更多的专卖店来代理售卖苹果手机,那么这样的编码会反复出现多次。一旦批发商发生改变或者售卖产品发生改变,代理商也必须跟随者做出相应的改变。

如何应对这种变化呢?

使用动态代理。

2.3 静态代理 >> 动态代理

改变代理对象的方法调用思路

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">InvocationTargetException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店A代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreA</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span>  <span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>;
​
    <span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#000000">Method</span> <span style="color:#000000">m</span>;
    <span style="color:#770088">static</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Class</span>.<span style="color:#000000">forName</span>(<span style="color:#aa1111">"com.qf.proxy._static.Seller"</span>).<span style="color:#000000">getMethod</span>(<span style="color:#aa1111">"sellPhoneX"</span>, <span style="color:#008855">double</span>.<span style="color:#770088">class</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">NoSuchMethodException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">ClassNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
    }
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesaler</span>){
        <span style="color:#770088">this</span>.<span style="color:#000000">wholesaler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">wholesaler</span>;
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1000</span>;
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">wholesaler</span>, <span style="color:#000000">price</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">IllegalAccessException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">InvocationTargetException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> (<span style="color:#000000">price</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
    }
}</span></span>

这里就出现了反射中 Method 对象,如果能够将 Method 对象的调用及前后实现的功能增强交给用户来实现,那么代理模式就可以为任何对象做代理了。

要实现用户自己定义增强功能,只能以接口的形式来定义,因为接口就是定义规则,用户遵守这个规则即可。那么如何来定义规则呢?分析代码不难发现,Method 对象的调用无非需要两个参数,一个是代理对象,一个是方法执行的参数。因为代理对象会变化,由用户自行决定,因此可以不考虑。那么就只剩下方法的参数了。而 Method 对象的调用也应该在用户的实现过程中,因此,Method对象也应该作为接口考虑的点。所以接口可以按下面的方式来定义:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">MethodInvocationHandler</span> {
​
    <span style="color:#008855">Object</span> <span style="color:#000000">invoke</span>(<span style="color:#000000">Method</span> <span style="color:#000000">method</span>, <span style="color:#008855">Object</span>[] <span style="color:#000000">args</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IllegalArgumentException</span>;
}</span></span>

此时使用 MethodInvocationHandler 来实现代理

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店A代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreA</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span>  <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>;
​
    <span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#000000">Method</span> <span style="color:#000000">m</span>;
    <span style="color:#770088">static</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Class</span>.<span style="color:#000000">forName</span>(<span style="color:#aa1111">"com.qf.proxy._static.Seller"</span>).<span style="color:#000000">getMethod</span>(<span style="color:#aa1111">"sellPhoneX"</span>, <span style="color:#008855">double</span>.<span style="color:#770088">class</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">NoSuchMethodException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">ClassNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
    }
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>){
        <span style="color:#770088">this</span>.<span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">handler</span>;
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#000000">handler</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">m</span>, <span style="color:#770088">new</span> <span style="color:#008855">Object</span>[]{ <span style="color:#000000">price</span> });
    }
}</span></span>

修改测试案例

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">InvocationTargetException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreATest</span> {
​
    <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#000000">main</span>(<span style="color:#008855">String</span>[] <span style="color:#000000">args</span>) {
        <span style="color:#000000">IPhoneWholesaler</span> <span style="color:#000000">wholesalerA</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneWholesaler</span>();
        <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">MethodInvocationHandler</span>() {
            <span style="color:#555555">@Override</span>
            <span style="color:#770088">public</span> <span style="color:#008855">Object</span> <span style="color:#000000">invoke</span>(<span style="color:#000000">Method</span> <span style="color:#000000">method</span>, <span style="color:#008855">Object</span>[] <span style="color:#000000">args</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IllegalArgumentException</span> {
                <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1000</span>;
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
                <span style="color:#008855">Object</span> <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#221199">null</span>;
                <span style="color:#770088">try</span> {
                    <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#000000">method</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">wholesalerA</span>, <span style="color:#000000">args</span>);
                } <span style="color:#770088">catch</span> (<span style="color:#000000">IllegalAccessException</span> <span style="color:#981a1a">|</span> <span style="color:#000000">InvocationTargetException</span> <span style="color:#000000">e</span>) {
                    <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
                }
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> ((<span style="color:#008855">double</span>)<span style="color:#000000">args</span>[<span style="color:#116644">0</span>] <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
                <span style="color:#770088">return</span> <span style="color:#000000">result</span>;
            }
        };
        <span style="color:#000000">IPhoneSpecialtyStoreA</span> <span style="color:#000000">specialtyStoreA</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">handler</span>);
        <span style="color:#000000">specialtyStoreA</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#116644">12000</span>);
    }
}</span></span>

批发商改变

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机批发商A</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneWholesalerNew</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"苹果手机批发商[NEW]卖手机价格为:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">price</span>);
    }
}</span></span>

再次修改测试案例

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">InvocationTargetException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreATest</span> {
​
    <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#000000">main</span>(<span style="color:#008855">String</span>[] <span style="color:#000000">args</span>) {
<span style="color:#aa5500">//        IPhoneWholesaler wholesalerA = new IPhoneWholesaler();</span>
        <span style="color:#000000">IPhoneWholesalerNew</span> <span style="color:#000000">wholesalerNew</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneWholesalerNew</span>();
        <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">MethodInvocationHandler</span>() {
            <span style="color:#555555">@Override</span>
            <span style="color:#770088">public</span> <span style="color:#008855">Object</span> <span style="color:#000000">invoke</span>(<span style="color:#000000">Method</span> <span style="color:#000000">method</span>, <span style="color:#008855">Object</span>[] <span style="color:#000000">args</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IllegalArgumentException</span> {
                <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1000</span>;
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
                <span style="color:#008855">Object</span> <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#221199">null</span>;
                <span style="color:#770088">try</span> {
                    <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#000000">method</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">wholesalerNew</span>, <span style="color:#000000">args</span>);
                } <span style="color:#770088">catch</span> (<span style="color:#000000">IllegalAccessException</span> <span style="color:#981a1a">|</span> <span style="color:#000000">InvocationTargetException</span> <span style="color:#000000">e</span>) {
                    <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
                }
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> ((<span style="color:#008855">double</span>)<span style="color:#000000">args</span>[<span style="color:#116644">0</span>] <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
                <span style="color:#770088">return</span> <span style="color:#000000">result</span>;
            }
        };
        <span style="color:#000000">IPhoneSpecialtyStoreA</span> <span style="color:#000000">specialtyStoreA</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">handler</span>);
        <span style="color:#000000">specialtyStoreA</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#116644">12000</span>);
    }
}</span></span>

到此,批发商改变问题就已经得到解决。

那么接下来需要考虑的就是大量的专卖店开进行代理售卖苹果手机的问题。那么就会产生大量的代理类。例如:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店B代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreB</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span>  <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>;
​
    <span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#000000">Method</span> <span style="color:#000000">m</span>;
    <span style="color:#770088">static</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Class</span>.<span style="color:#000000">forName</span>(<span style="color:#aa1111">"com.qf.proxy._static.Seller"</span>).<span style="color:#000000">getMethod</span>(<span style="color:#aa1111">"sellPhoneX"</span>, <span style="color:#008855">double</span>.<span style="color:#770088">class</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">NoSuchMethodException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">ClassNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
    }
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreB</span>(<span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>){
        <span style="color:#770088">this</span>.<span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">handler</span>;
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#000000">handler</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">m</span>, <span style="color:#770088">new</span> <span style="color:#008855">Object</span>[]{ <span style="color:#000000">price</span> });
    }
}</span></span>

这些类都是属于代理,都使用了 MethodInvocationHandler 来完成代理的功能。可以将这些共有的功能抽取到父类中。

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
<span style="color:#aa5500">//因为是给代理继承使用,因此父类命名带有Proxy,创建出来的对象自然称为代理</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">MyProxy</span> {
​
    <span style="color:#770088">protected</span> <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>;
​
    <span style="color:#770088">protected</span> <span style="color:#000000">MyProxy</span>(<span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>) {
        <span style="color:#770088">this</span>.<span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">handler</span>;
    }
}
​
<span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店A代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreA</span> <span style="color:#770088">extends</span> <span style="color:#000000">MyProxy</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#000000">Method</span> <span style="color:#000000">m</span>;
    <span style="color:#770088">static</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Class</span>.<span style="color:#000000">forName</span>(<span style="color:#aa1111">"com.qf.proxy._static.Seller"</span>).<span style="color:#000000">getMethod</span>(<span style="color:#aa1111">"sellPhoneX"</span>, <span style="color:#008855">double</span>.<span style="color:#770088">class</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">NoSuchMethodException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">ClassNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
    }
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreA</span>(<span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>){
        <span style="color:#770088">super</span>(<span style="color:#000000">handler</span>);
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#000000">handler</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">m</span>, <span style="color:#770088">new</span> <span style="color:#008855">Object</span>[]{ <span style="color:#000000">price</span> });
    }
}
​
<span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#aa5500">/**</span>
 <span style="color:#aa5500">* 苹果手机专卖店B代理卖苹果手机</span>
 <span style="color:#aa5500">*/</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">IPhoneSpecialtyStoreB</span> <span style="color:#770088">extends</span> <span style="color:#000000">MyProxy</span> <span style="color:#770088">implements</span> <span style="color:#000000">Seller</span>{
​
    <span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#000000">Method</span> <span style="color:#000000">m</span>;
    <span style="color:#770088">static</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">m</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Class</span>.<span style="color:#000000">forName</span>(<span style="color:#aa1111">"com.qf.proxy._static.Seller"</span>).<span style="color:#000000">getMethod</span>(<span style="color:#aa1111">"sellPhoneX"</span>, <span style="color:#008855">double</span>.<span style="color:#770088">class</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">NoSuchMethodException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">ClassNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
    }
​
    <span style="color:#770088">public</span> <span style="color:#000000">IPhoneSpecialtyStoreB</span>(<span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>){
        <span style="color:#770088">super</span>(<span style="color:#000000">handler</span>);
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">sellPhoneX</span>(<span style="color:#008855">double</span> <span style="color:#000000">price</span>) {
        <span style="color:#000000">handler</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">m</span>, <span style="color:#770088">new</span> <span style="color:#008855">Object</span>[]{ <span style="color:#000000">price</span> });
    }
}</span></span>

共有的功能抽取只是解决代码冗余问题,并没有解决上面提到的代理繁多的问题。如果这些代理类能够

使用代码来生成,然后再编译,再加载至 JVM 中,那么再多的代理也就不是问题了。

参照 IPhoneSpecialtyStoreA 来编写代理类生成代码,在 MyProxy 中编写如下方法:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#008855">String</span> <span style="color:#0000ff">generateProxyClass</span>(<span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">clazz</span>){
    <span style="color:#770088">if</span>(<span style="color:#981a1a">!</span><span style="color:#000000">clazz</span>.<span style="color:#000000">isInterface</span>()) <span style="color:#770088">throw</span> <span style="color:#770088">new</span> <span style="color:#000000">IllegalArgumentException</span>(<span style="color:#000000">clazz</span>.<span style="color:#000000">getName</span>() <span style="color:#981a1a">+</span> <span style="color:#aa1111">" 不是接口"</span>);
    <span style="color:#008855">StringBuilder</span> <span style="color:#000000">builder</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#008855">StringBuilder</span>();
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"package "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">clazz</span>.<span style="color:#000000">getPackage</span>().<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">";\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"import "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">Method</span>.<span style="color:#770088">class</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">";\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"import "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">MethodInvocationHandler</span>.<span style="color:#770088">class</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">";\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"import "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">MyProxy</span>.<span style="color:#770088">class</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">";\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"public class $proxy0 extends MyProxy implements "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">clazz</span>.<span style="color:#000000">getSimpleName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">"{\n"</span>);
    <span style="color:#008855">StringBuilder</span> <span style="color:#000000">staticBuilder</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#008855">StringBuilder</span>();
    <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"static {\n"</span>);
    <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"try {\n"</span>);
    <span style="color:#008855">StringBuilder</span> <span style="color:#000000">overrideMethodBuilder</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#008855">StringBuilder</span>();
    <span style="color:#000000">Method</span>[] <span style="color:#000000">methods</span> <span style="color:#981a1a">=</span> <span style="color:#000000">clazz</span>.<span style="color:#000000">getMethods</span>();
    <span style="color:#770088">for</span>(<span style="color:#008855">int</span> <span style="color:#000000">i</span><span style="color:#981a1a">=</span><span style="color:#116644">0</span>; <span style="color:#000000">i</span><span style="color:#981a1a"><</span><span style="color:#000000">methods</span>.<span style="color:#000000">length</span>; <span style="color:#000000">i</span><span style="color:#981a1a">++</span>){
        <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"private static Method m"</span>).<span style="color:#000000">append</span>(<span style="color:#000000">i</span>).<span style="color:#000000">append</span>(<span style="color:#aa1111">";\n"</span>);
        <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"m"</span>).<span style="color:#000000">append</span>(<span style="color:#000000">i</span>).<span style="color:#000000">append</span>(<span style="color:#aa1111">"=Class.forName(\""</span>).<span style="color:#000000">append</span>(<span style="color:#000000">clazz</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">"\").getMethod(\""</span>)
            .<span style="color:#000000">append</span>(<span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">"\","</span>);
        <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"\n@Override\n"</span>);
        <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"public "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getReturnType</span>().<span style="color:#000000">getSimpleName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">" "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">"("</span>);
        <span style="color:#000000">Parameter</span>[] <span style="color:#000000">parameters</span> <span style="color:#981a1a">=</span> <span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getParameters</span>();
        <span style="color:#770088">for</span>(<span style="color:#000000">Parameter</span> <span style="color:#000000">parameter</span> : <span style="color:#000000">parameters</span>){
            <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#000000">parameter</span>.<span style="color:#000000">getType</span>().<span style="color:#000000">getSimpleName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">".class,"</span>);
            <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#000000">parameter</span>.<span style="color:#000000">getType</span>().<span style="color:#000000">getSimpleName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">" "</span>).<span style="color:#000000">append</span>(<span style="color:#000000">parameter</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">","</span>);
        }
        <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">deleteCharAt</span>(<span style="color:#000000">staticBuilder</span>.<span style="color:#000000">length</span>()<span style="color:#981a1a">-</span><span style="color:#116644">1</span>);
        <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">");\n"</span>);
        <span style="color:#770088">if</span>(<span style="color:#000000">parameters</span>.<span style="color:#000000">length</span> <span style="color:#981a1a">></span> <span style="color:#116644">0</span>)
            <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">deleteCharAt</span>(<span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">length</span>()<span style="color:#981a1a">-</span><span style="color:#116644">1</span>);
        <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"){\n"</span>);
        <span style="color:#000000">Class</span> <span style="color:#000000">returnType</span> <span style="color:#981a1a">=</span> <span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getReturnType</span>();
        <span style="color:#770088">if</span>(<span style="color:#000000">returnType</span> <span style="color:#981a1a">!=</span> <span style="color:#008855">Void</span>.<span style="color:#770088">class</span> <span style="color:#981a1a">&&</span> <span style="color:#000000">returnType</span> <span style="color:#981a1a">!=</span> <span style="color:#008855">void</span>.<span style="color:#770088">class</span>)
            <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"return ("</span>).<span style="color:#000000">append</span>(<span style="color:#000000">methods</span>[<span style="color:#000000">i</span>].<span style="color:#000000">getReturnType</span>().<span style="color:#000000">getSimpleName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">")"</span>);
        <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"handler.invoke(m"</span>).<span style="color:#000000">append</span>(<span style="color:#000000">i</span>).<span style="color:#000000">append</span>(<span style="color:#aa1111">",new Object[]{"</span>);
        <span style="color:#770088">for</span>(<span style="color:#000000">Parameter</span> <span style="color:#000000">parameter</span> : <span style="color:#000000">parameters</span>){
            <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#000000">parameter</span>.<span style="color:#000000">getName</span>()).<span style="color:#000000">append</span>(<span style="color:#aa1111">","</span>);
        }
        <span style="color:#770088">if</span>(<span style="color:#000000">parameters</span>.<span style="color:#000000">length</span> <span style="color:#981a1a">></span> <span style="color:#116644">0</span>)
            <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">deleteCharAt</span>(<span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">length</span>()<span style="color:#981a1a">-</span><span style="color:#116644">1</span>);
        <span style="color:#000000">overrideMethodBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"});\n}"</span>);
    }
    <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"} catch (NoSuchMethodException e) {\ne.printStackTrace();\n}catch (ClassNotFoundException e) {\ne.printStackTrace();\n}\n"</span>);
    <span style="color:#000000">staticBuilder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"}\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#000000">staticBuilder</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"protected $proxy0(MethodInvocationHandler handler) {\nsuper(handler);\n}\n"</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#000000">overrideMethodBuilder</span>);
    <span style="color:#000000">builder</span>.<span style="color:#000000">append</span>(<span style="color:#aa1111">"\n}"</span>);
    <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#000000">builder</span>);
    <span style="color:#770088">return</span> <span style="color:#000000">builder</span>.<span style="color:#000000">toString</span>();
}</span></span>

将生成的代理类保存至磁盘中,在 MyProxy 中编写如下方法:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#0000ff">saveProxyClass</span>(<span style="color:#008855">String</span> <span style="color:#000000">proxyClass</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IOException</span> {
    <span style="color:#008855">String</span> <span style="color:#000000">path</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"d:\\$proxy0.java"</span>;
    <span style="color:#000000">BufferedWriter</span> <span style="color:#000000">writer</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">BufferedWriter</span>(<span style="color:#770088">new</span> <span style="color:#000000">FileWriter</span>(<span style="color:#000000">path</span>));
    <span style="color:#000000">writer</span>.<span style="color:#000000">write</span>(<span style="color:#000000">proxyClass</span>);
    <span style="color:#000000">writer</span>.<span style="color:#000000">flush</span>();
    <span style="color:#000000">writer</span>.<span style="color:#000000">close</span>();
}</span></span>

编译代理类源文件,在 MyProxy 中编写如下方法:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">private</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#0000ff">compile</span>() <span style="color:#770088">throws</span> <span style="color:#000000">IOException</span> {
    <span style="color:#000000">File</span> <span style="color:#000000">javaFile</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">File</span>(<span style="color:#aa1111">"d:\\$proxy0.java"</span>);
    <span style="color:#000000">JavaCompiler</span> <span style="color:#000000">compiler</span> <span style="color:#981a1a">=</span> <span style="color:#000000">ToolProvider</span>.<span style="color:#000000">getSystemJavaCompiler</span>();
    <span style="color:#000000">DiagnosticCollector</span> <span style="color:#000000">diagnostics</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">DiagnosticCollector</span>();
    <span style="color:#000000">StandardJavaFileManager</span> <span style="color:#000000">fileManager</span> <span style="color:#981a1a">=</span> <span style="color:#000000">compiler</span>.<span style="color:#000000">getStandardFileManager</span>(<span style="color:#000000">diagnostics</span>, <span style="color:#221199">null</span>, <span style="color:#221199">null</span>);
    <span style="color:#000000">Iterable</span><span style="color:#981a1a"><?</span> <span style="color:#770088">extends</span> <span style="color:#000000">JavaFileObject</span><span style="color:#981a1a">></span> <span style="color:#000000">javaFileObjects</span> <span style="color:#981a1a">=</span> <span style="color:#000000">fileManager</span>.<span style="color:#000000">getJavaFileObjects</span>(<span style="color:#000000">javaFile</span>);
    <span style="color:#000000">JavaCompiler</span>.<span style="color:#000000">CompilationTask</span> <span style="color:#000000">task</span> <span style="color:#981a1a">=</span> <span style="color:#000000">compiler</span>.<span style="color:#000000">getTask</span>(<span style="color:#221199">null</span>, <span style="color:#000000">fileManager</span>, <span style="color:#221199">null</span>,<span style="color:#221199">null</span>,<span style="color:#221199">null</span>, <span style="color:#000000">javaFileObjects</span>);
    <span style="color:#000000">task</span>.<span style="color:#000000">call</span>();
    <span style="color:#000000">fileManager</span>.<span style="color:#000000">close</span>();
}</span></span>

加载编译好的代理类,这里需要自定义类加载器

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#981a1a">*</span>;
​
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">MyClassLoader</span> <span style="color:#770088">extends</span> <span style="color:#000000">ClassLoader</span>{
​
    <span style="color:#770088">private</span> <span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">clazz</span>;
​
    <span style="color:#770088">private</span> <span style="color:#000000">File</span> <span style="color:#000000">dir</span>;
​
    <span style="color:#770088">public</span> <span style="color:#000000">MyClassLoader</span>(<span style="color:#000000">File</span> <span style="color:#000000">dir</span>, <span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">clazz</span>){
        <span style="color:#770088">this</span>.<span style="color:#000000">dir</span> <span style="color:#981a1a">=</span> <span style="color:#000000">dir</span>;
        <span style="color:#770088">this</span>.<span style="color:#000000">clazz</span> <span style="color:#981a1a">=</span> <span style="color:#000000">clazz</span>;
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">findClass</span>(<span style="color:#008855">String</span> <span style="color:#000000">name</span>) <span style="color:#770088">throws</span> <span style="color:#000000">ClassNotFoundException</span> {
        <span style="color:#770088">try</span> {
            <span style="color:#000000">InputStream</span> <span style="color:#000000">is</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">FileInputStream</span>(<span style="color:#770088">new</span> <span style="color:#000000">File</span>(<span style="color:#000000">dir</span>, <span style="color:#000000">name</span>));
            <span style="color:#008855">int</span> <span style="color:#000000">available</span> <span style="color:#981a1a">=</span> <span style="color:#000000">is</span>.<span style="color:#000000">available</span>();
            <span style="color:#008855">byte</span>[] <span style="color:#000000">buffer</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#008855">byte</span>[<span style="color:#000000">available</span>];
            <span style="color:#000000">is</span>.<span style="color:#000000">read</span>(<span style="color:#000000">buffer</span>);
            <span style="color:#000000">is</span>.<span style="color:#000000">close</span>();
            <span style="color:#770088">return</span> <span style="color:#000000">defineClass</span>(<span style="color:#000000">clazz</span>.<span style="color:#000000">getPackage</span>().<span style="color:#000000">getName</span>() <span style="color:#981a1a">+</span> <span style="color:#aa1111">".$proxy0"</span>, <span style="color:#000000">buffer</span>, <span style="color:#116644">0</span>, <span style="color:#000000">buffer</span>.<span style="color:#000000">length</span>);
        } <span style="color:#770088">catch</span> (<span style="color:#000000">FileNotFoundException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        } <span style="color:#770088">catch</span> (<span style="color:#000000">IOException</span> <span style="color:#000000">e</span>) {
            <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
        }
        <span style="color:#770088">return</span> <span style="color:#770088">super</span>.<span style="color:#000000">loadClass</span>(<span style="color:#000000">name</span>);
    }
}</span></span>

编写创建代理实例的方法,在 MyProxy 中编写如下方法:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">Object</span> <span style="color:#0000ff">newProxyInstance</span>(<span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">clazz</span>, <span style="color:#000000">MyClassLoader</span> <span style="color:#000000">loader</span>, <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IOException</span>, <span style="color:#000000">ClassNotFoundException</span>, <span style="color:#000000">NoSuchMethodException</span>, <span style="color:#000000">IllegalAccessException</span>, <span style="color:#000000">InvocationTargetException</span>, <span style="color:#000000">InstantiationException</span> {
    <span style="color:#008855">String</span> <span style="color:#000000">proxyClass</span> <span style="color:#981a1a">=</span> <span style="color:#000000">generateProxyClass</span>(<span style="color:#000000">clazz</span>);
    <span style="color:#000000">saveProxyClass</span>(<span style="color:#000000">proxyClass</span>);
    <span style="color:#000000">compileProxyClass</span>();
    <span style="color:#000000">Class</span><span style="color:#981a1a"><?></span> <span style="color:#000000">cl</span> <span style="color:#981a1a">=</span> <span style="color:#000000">loader</span>.<span style="color:#000000">findClass</span>(<span style="color:#aa1111">"$proxy0.class"</span>);
    <span style="color:#000000">Constructor</span><span style="color:#981a1a"><?></span> <span style="color:#000000">constructor</span> <span style="color:#981a1a">=</span> <span style="color:#000000">cl</span>.<span style="color:#000000">getDeclaredConstructor</span>(<span style="color:#000000">MethodInvocationHandler</span>.<span style="color:#770088">class</span>);
    <span style="color:#000000">constructor</span>.<span style="color:#000000">setAccessible</span>(<span style="color:#221199">true</span>);
    <span style="color:#770088">return</span> <span style="color:#000000">constructor</span>.<span style="color:#000000">newInstance</span>(<span style="color:#000000">handler</span>);
}</span></span>

编写测试案例

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">qf</span>.<span style="color:#000000">proxy</span>.<span style="color:#000000">_static</span>;
​
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">File</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">IOException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">InvocationTargetException</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">lang</span>.<span style="color:#000000">reflect</span>.<span style="color:#000000">Method</span>;
​
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">MyProxyTest</span> {
​
    <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#008855">void</span> <span style="color:#000000">main</span>(<span style="color:#008855">String</span>[] <span style="color:#000000">args</span>) <span style="color:#770088">throws</span> <span style="color:#000000">NoSuchMethodException</span>, <span style="color:#000000">IOException</span>, <span style="color:#000000">InstantiationException</span>, <span style="color:#000000">IllegalAccessException</span>, <span style="color:#000000">InvocationTargetException</span>, <span style="color:#000000">ClassNotFoundException</span> {
        <span style="color:#000000">IPhoneWholesalerNew</span> <span style="color:#000000">wholesalerNew</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">IPhoneWholesalerNew</span>();
        <span style="color:#000000">MethodInvocationHandler</span> <span style="color:#000000">handler</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">MethodInvocationHandler</span>() {
            <span style="color:#555555">@Override</span>
            <span style="color:#770088">public</span> <span style="color:#008855">Object</span> <span style="color:#000000">invoke</span>(<span style="color:#000000">Method</span> <span style="color:#000000">method</span>, <span style="color:#008855">Object</span>[] <span style="color:#000000">args</span>) <span style="color:#770088">throws</span> <span style="color:#000000">IllegalArgumentException</span> {
                <span style="color:#008855">double</span> <span style="color:#000000">profit</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1000</span>;
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"代理盈利:"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>);
                <span style="color:#008855">Object</span> <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#221199">null</span>;
                <span style="color:#770088">try</span> {
                    <span style="color:#000000">result</span> <span style="color:#981a1a">=</span> <span style="color:#000000">method</span>.<span style="color:#000000">invoke</span>(<span style="color:#000000">wholesalerNew</span>, <span style="color:#000000">args</span>);
                } <span style="color:#770088">catch</span> (<span style="color:#000000">IllegalAccessException</span> <span style="color:#981a1a">|</span> <span style="color:#000000">InvocationTargetException</span> <span style="color:#000000">e</span>) {
                    <span style="color:#000000">e</span>.<span style="color:#000000">printStackTrace</span>();
                }
                <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"卖出价格:"</span> <span style="color:#981a1a">+</span> ((<span style="color:#008855">double</span>)<span style="color:#000000">args</span>[<span style="color:#116644">0</span>] <span style="color:#981a1a">+</span> <span style="color:#000000">profit</span>));
                <span style="color:#770088">return</span> <span style="color:#000000">result</span>;
            }
        };
        <span style="color:#000000">MyClassLoader</span> <span style="color:#000000">loader</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">MyClassLoader</span>(<span style="color:#770088">new</span> <span style="color:#000000">File</span>(<span style="color:#aa1111">"d:\\"</span>), <span style="color:#000000">Seller</span>.<span style="color:#770088">class</span>);
        <span style="color:#000000">Seller</span> <span style="color:#000000">seller</span> <span style="color:#981a1a">=</span> (<span style="color:#000000">Seller</span>) <span style="color:#000000">MyProxy</span>.<span style="color:#000000">newProxyInstance</span>(<span style="color:#000000">Seller</span>.<span style="color:#770088">class</span>, <span style="color:#000000">loader</span>, <span style="color:#000000">handler</span>);
        <span style="color:#000000">seller</span>.<span style="color:#000000">sellPhoneX</span>(<span style="color:#116644">12000</span>);
    }
}</span></span>

到此代理繁多的问题也就是 解决了,这种实现方式称之为动态代理。

思考:如果实现多个接口,怎么处理?

3. 动态代理

动态代理根据代理的实现又分为 JDK 动态代理和 CGLIB 动态代理。如果是对接口做代理,那么使用的 JDK 动态代理;如果是对类做代理,那么使用的就是 CGLIB 动态代理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

代理模式详解 的相关文章

  • 使用 JDBC 获取 Oracle 11g 的最后插入 ID

    我是使用 Oracle 的新手 所以我将放弃之前已经回答过的内容这个问题 https stackoverflow com questions 3131064 get id of last inserted record in oracle
  • Java 7 默认语言环境

    我刚刚安装了 jre7 我很惊讶地发现我的默认区域设置现在是 en US 对于jre6 它是de CH 与jre7有什么不同 默认区域设置不再是操作系统之一吗 顺便说一句 我使用的是Windows7 谢谢你的回答 编辑 我已经看到了语言环境
  • 如何使用 JAVA 代码以编程方式捕获线程转储?

    我想通过 java 代码生成线程转储 我尝试使用 ThreadMXBean 为此 但我没有以正确的格式获得线程转储 因为我们正在使用jstack命令 请任何人提供一些帮助 他们是否有其他方式获取线程转储 使用任何其他 API 我想要的线程转
  • Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?

    我创建了一个 RestController 如下所示 RestController public class GreetingController RequestMapping value greetings method RequestM
  • 文本在指定长度后分割,但不要使用 grails 打断单词

    我有一个长字符串 需要将其解析为长度不超过 50 个字符的字符串数组 对我来说 棘手的部分是确保正则表达式找到 50 个字符之前的最后一个空格 以便在字符串之间进行彻底的分隔 因为我不希望单词被切断 public List
  • tomcat 7.0.50 java websocket 实现给出 404 错误

    我正在尝试使用 Java Websocket API 1 0 JSR 356 中指定的带注释端点在 tomcat 7 0 50 上实现 websocket 以下是我如何对其进行编码的简要步骤 1 使用 ServerEndpoint注解编写w
  • 如何在java Spring Boot中实现通用服务类?

    我有许多具有重复代码的服务 我想知道如何实现通用服务 以便我的所有服务都可以扩展它 服务接口示例 重复代码 Service public interface IUserService List
  • 如何检测图像是否像素化

    之前有人在 SO 上提出过这样的问题 在Python中检测像素化图像 https stackoverflow com questions 12942365 detecting a pixelated image in python还有关于q
  • Java中的断点和逐步调试?

    抱歉我的问题名称很奇怪 我不知道如何寻找这个 因为我不知道这些东西是如何称呼的 Visual Studio 中至少有一个功能 您可以单击代码左侧并设置一个大红点的起点 然后运行程序 您可以通过按 f8 或 f5 实际上是不同的 f 来跟踪步
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 如何删除日期对象的亚秒部分

    当 SQL 数据类型为时间戳时 java util Date 存储为 2010 09 03 15 33 22 246 如何在存储记录之前将亚秒设置为零 例如 在本例中为 246 最简单的方法是这样的 long time date getTi
  • Java、Spring:使用 Mockito 测试 DAO 的 DataAccessException

    我正在尝试增加测试覆盖率 所以我想知道 您将如何测试 DAO 中抛出的 DataAccessExceptions 例如在一个简单的 findAll 方法中 该方法仅返回数据源中的所有数据 就我而言 我使用 Spring JdbcTempla
  • 如何从日期中删除毫秒、秒、分钟和小时[重复]

    这个问题在这里已经有答案了 我遇到了一个问题 我想比较两个日期 然而 我只想比较年 月 日 这就是我能想到的 private Date trim Date date Calendar calendar Calendar getInstanc
  • 如何通过 Android 按钮单击运行单独的应用程序

    我尝试在 Android 应用程序中添加两个按钮 以从单独的两个应用程序订单系统和库存系统中选择一个应用程序 如图所示 我已将这两个应用程序实现为两个单独的 Android 项目 当我尝试运行此应用程序时 它会出现直到正确选择窗口 但是当按
  • 如何停止执行的 Jar 文件

    这感觉像是一个愚蠢的问题 但我似乎无法弄清楚 当我在 Windows 上运行 jar 文件时 它不会出现在任务管理器进程中 我怎样才能终止它 我已经尝试过 TASKKILL 但它对我也不起作用 On Linux ps ef grep jav
  • Play.application() 的替代方案是什么

    我是 Play 框架的新手 我想读取conf文件夹中的一个文件 所以我用了Play application classloader getResources Data json nextElement getFile 但我知道 play P
  • 如何在Java中对对象数组进行字段级别排序以进行等级比较?

    In Java Class StudentProgress String Name String Grade CTOR goes here main class main method StudentProgress arrayofObje
  • 使用 Java https 上传到 Imgur v3 错误

    我目前正在尝试使用他们当前的 API v3 上传到 imgur 但是我不断收到错误 错误 javax net ssl SSLException 证书中的主机名不匹配 api imgur com imgur com OR imgur com
  • Java 的 PriorityQueue 与最小堆有何不同?

    他们为什么命名PriorityQueue如果你不能插入优先级 它看起来与堆非常相似 有什么区别吗 如果没有区别那为什么叫它PriorityQueue而不是堆 默认的PriorityQueue是用Min Heap实现的 即栈顶元素是堆中最小的

随机推荐

  • linux 日志查看

    Linux 查看日志相关命令总结 Linux日志筛选命令 常用Linux日志查看命令 grep常用用法 zgrep 不解压过滤压缩包中文本 Linux命令大全 手册 循环实时查看最后50行记录 tailf n 50 tomcat stdou
  • 在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点)...

    最近 在论坛中 遇到了不少比较难的sql问题 虽然自己都能解决 但发现过几天后 就记不起来了 也忘记解决的方法了 所以 觉得有必要记录下来 这样以后再次碰到这类问题 也能从中获取解答的思路 问题 求SQL 检索某个节点下所有叶子节点 部门表
  • centos7配置yum为国内源

    问题 yum install libXm so 4 报错 Cannot find a valid baseurl for repo base 7 x86 64 因为yum源不是国内的 切换一下 步骤 卸载 yum rpm aq grep y
  • 字节青训营第十三课之深入浅出RPC框架的笔记与总结.md

    基本概念 本地函数调用 函数调用完整过程如图 藏实际上编译器经常优化 参数和返回值少时直接将其存在寄存器 不需操作栈 直接online不需call 将a和b的值入栈 经函数指针找到calculate 进入函数取栈中值2和3赋给x和y 计算x
  • C# GDI+ 绘图

    1 坐标系统 1 坐标原点 在窗体或控件的左上角 坐标为 0 0 2 正方向 X轴正方向为水平向右 Y轴正方向为竖直向下 3 单位 在设置时 一般以像素为单位 像素 Pixel 是由图像 Picture 和元素 Element 组成 是用来
  • 怎么在百度里通过关键词搜索到自己的网站

    1 需要在百度站长平台提交自己的网址 2进入百度站长平台 点击链接提交 3 点击添加站点 等待百度收录之后 4 在百度搜索框中输入 如下图 site后面的是你的域名 然后空格 加你要搜索的关键词 在该域名上的网页上要有该关键字 5 输入关键
  • git bash 命令行反应慢、卡顿

    1 在Windows11的电脑上安装了git 后 鼠标右键打开git bash here 打开窗口缓慢 输入命令也慢的要死 如果安装git的时候选择在桌面创建图标 通过桌面图标打开也是一样的 2 最简单的ls 命令 都要停顿半秒 3 点击桌
  • Flops 计算以及代码快速查看网络参数、浮点数

    详细计算 卷积神经网络CNN中的参数量 parameters 和计算量 FLOPs 知乎 FLOPS 全大写 指每秒浮点运算次数 可以理解为计算的速度 是衡量硬件性能的一个指标 硬件 FLOPs s小写 指浮点运算数 理解为计算量 可以用来
  • Lattice CrosslinkNx LIFCL-40应用连载5:如何使用MIPI D-PHY硬核IP

    作者 Hello Panda 一 目标 配置CMOS Sensor OV9734 并通过MIPI DPHY硬核接收数据 使用一个RISC V软核 实通过AHB总线访问I2C FIFO 通过I2C总线配置OV9734 Sensor 使用MIP
  • 基于VS调试分析 + 堆栈观察问题代码段

    文章目录 问题代码段1 阶乘之和 问题代码段2 越界的危害 发现问题 分析问题 思考问题 堆栈原理 解决问题 DeBug与Release 程序员与测试人员 总结与提炼 问题代码段1 阶乘之和 先来看一道C语言中比较基础的题目 求解阶乘的和
  • java --向上转型和向下转型

    一 简述 Java 转型主要是用在继承和接口实现的场景 Java 转型可分为向上转型和向下转型 区别如下 向上转型 通过子类对象实例化父类对象 这属于自动转换 向下转型 通过父类对象实例化子类对象 这属于强制转换 只要记住一句话即可 父类引
  • JAVA 多态 从内存角度分析

    设父类对象占内存空间100M 子类对象占内存空间50M 问题 对象转型问题 为什么只有父类变量指向子类对象 因为父类需要100M 只能指向比自己更大的空间 父类变量指向子类对象时变量情况 a pa c cc 父类变量实际上指向的是 和 pc
  • Python Pytest装饰器@pytest.mark.parametrize详解

    转自 Python Pytest装饰器 pytest mark parametrize详解 Pytest中装饰器 pytest mark parametrize 参数名 list 可以实现测试用例参数化 类似DDT 如 pytest mar
  • http的异步请求

    需要用到的包 包版本应该可能不同 httpcore 4 1 4 jar httpsayncclient 4 0 alpha3 jar httpcore nio 4 2 alpha3 jar 异步http请求 author Old Zhang
  • ci分页查询ajax,解析CI的AJAX分页 另类实现方法_PHP教程

    看了一下CI的分页类没有写到关于AJAX的内容 也在论坛上看到其他几位大神写的分页类扩展 感觉其实是没有必要 在现有的基础上做了一下小小的改动还是能实现的 下面进入正题 CI的原生分页类中有一个参数 config anchor class
  • Whistle抓包之设置windows全局代理

    一 whistle官网教程 http wproxy org whistle install html 二 windows场景设置全局代理 因为博主在设置SwitchyOmega插件代理时 未生效 只能通过设置全局代理的方式解决 官网教程上又
  • 华为OD机试 - 机房布局(Java)

    题目描述 小明正在规划一个大型数据中心机房 为了使得机柜上的机器都能正常满负荷工作 需要确保在每个机柜边上至少要有一个电箱 为了简化题目 假设这个机房是一整排 M表示机柜 I表示间隔 请你返回这整排机柜 至少需要多少个电箱 如果无解请返回
  • Vue触底加载

    页面内的触底加载 需求 页面滚动到接近底部 再次发送请求 获取更多数据 渲染到页面上 data 请求页数 page 0 请求获取的数据 list 是否正在加载 用于节流 isLoading false created 首次调用 this g
  • 一篇文章教你,破解百度网盘加密文件,学会这个举一反二

    经常遇到百度网盘的压缩文件加密了 今天我们就破解它 实现思路 爆破密码的思路其实都大同小异 无非就是字典爆破 就看你是有现成密码字典 还是自己生成密码字典 然后进行循环输入密码 直到输入正确位置 现在很多都有防爆破限制 根本无法进行暴力破解
  • 代理模式详解

    第一节 代理模式介绍 1 什么是代理模式 代理 Proxy 是一种设计模式 提供了对目标对象另外的访问方式 即通过代理对象访问目标对象 这样做的好处是 可以在目标对象实现的基础上 增强额外的功能操作 即扩展目标对象的功能 代理模式分为静态代