<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] 所謂代理代理模式可以在不修改被代理對象的基礎上,**通過擴展代理類,進行一些功能的附加與增強**。值得注意的是,代理類和被代理類應該共同實現一個接口,或者是共同繼承某個類。 比如,代理類可以補充一些打印日志,統計時長的方法。 ## Java 靜態代理 ~~~ //通用的接口 public interface Movie { void play(); } //真正的實現這個 Movie 接口的類 public class RealMovie implements Movie { @Override public void play() { System.out.println("您正在觀看電影 《肖申克的救贖》"); } } //代理類 public class Cinema implements Movie { RealMovie movie; public Cinema(RealMovie movie) { super(); this.movie = movie; } @Override public void play() { guanggao(true); movie.play(); guanggao(false); } public void guanggao(boolean isStart){ if ( isStart ) { System.out.println("電影馬上開始了"); } else { System.out.println("電影馬上結束了"); } } } // 方法 public class ProxyTest { public static void main(String[] args) { RealMovie realmovie = new RealMovie(); Movie movie = new Cinema(realmovie); movie.play(); ~~~ ## Java 動態代理 ### Demo ~~~ //通用的接口 public interface SellWine { void mainJiu(); } //真正的實現類 public class MaotaiJiu implements SellWine { @Override public void mainJiu() { // TODO Auto-generated method stub System.out.println("我賣得是茅臺酒。"); } } //代理類 public class GuitaiA implements InvocationHandler { private Object pingpai; public GuitaiA(Object pingpai) { this.pingpai = pingpai; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("銷售開始:"+this.getClass().getSimpleName()); method.invoke(pingpai, args); System.out.println("銷售結束"); return null; } } public class Test { public static void main(String[] args) { MaotaiJiu maotaijiu = new MaotaiJiu(); InvocationHandler jingxiao1 = new GuitaiA(maotaijiu); SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(), MaotaiJiu.class.getInterfaces(), jingxiao1); dynamicProxy.mainJiu(); } } 結果; 銷售開始 GuitaiA 我賣得是茅 ~~~ ### 語法 #### Proxy 動態代碼涉及了一個非常重要的類 Proxy。正是通過 Proxy 的靜態方法 newProxyInstance才會動態創建代理的實例對象。 ~~~ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ~~~ 下面講解它的 3 個參數意義。 * loader 自然是類加載器 * interfaces 代碼要用來代理的接口 * h 一個 InvocationHandler 對象 #### InvocationHandler InvocationHandler 是一個接口,官方文檔解釋說,每個代理的實例都有一個與之關聯的 InvocationHandler 實現類,如果代理的方法被調用,那么代理便會通知和轉發給內部的 InvocationHandler 實現類,由它決定處理 ~~~ public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; } ~~~ * proxy 代理對象 * method 代理對象調用的方法 * args 調用的方法中的參數 ### 原理 #### newProxyInstance newProxyInstance 實際上就是動態生成的代理類,類名是**包名+$Proxy+id序號**。 ~~~ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); //核心方法 創建類定義 Class<?> cl = getProxyClass0(loader, intfs); try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; ...。 //反射初始化 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { .. } ~~~ #### getProxyClass0 ~~~ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { ... 。 // 直接通過緩存獲取,如果獲取不到,注釋說會通過 ProxyClassFactory 生成。 return proxyClassCache.get(loader, interfaces); } ~~~ #### ProxyClassFactory? ~~~ /** * A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces. */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // Proxy class 的前綴是 “$Proxy”, private static final String proxyClassNamePrefix = "$Proxy"; // next number to use for generation of unique proxy class names private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ Class<?> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " 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.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // package to define proxy class in int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* * 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 (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { accessFlags = Modifier.FINAL; String name = intf.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 com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* * Choose a name for the proxy class to generate. */ long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } ~~~ defineClass0() 甚至是一個 native 方法。我們只要知道,動態創建代理這回事就好了。 ## Android 通過動態代理設置事件監聽 ~~~ public class MainActivity extends AppCompatActivity { private Button bt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt = (Button) findViewById(R.id.bt); proxySetOnclick(); } //通過代理為button設置監聽 private void proxySetOnclick() { try { //獲得真實回調的方法(后期可以用注解獲得這里hardCode了) Method realClick = this.getClass().getMethod("realClick",View.class); //創建一個代理 ProxyHandle handle = new ProxyHandle(this, realClick); //設置代理 返回的是對應的接口 (OnClickListener實例對象) View.OnClickListener proxyObj = (View.OnClickListener)Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class[]{View.OnClickListener.class}, handle); //調用對應View的設置監聽方法 之后會到代理handle里去(對象可以用注解獲得這里暫不分析) bt.setOnClickListener(proxyObj); } catch (Exception e) { e.printStackTrace(); } } //真實回調方法 public void realClick(View v) { Toast.makeText(this,"點擊了",Toast.LENGTH_SHORT).show(); } } public class ProxyHandle implements InvocationHandler { private Object realObj; private Method realMethod; public ProxyHandle(Object realObj,Method realMethod){ this.realObj=realObj; this.realMethod=realMethod; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果真實對象跟方法都不為null 則直接返回真是方法(這里真實方法必須跟接口方法參數保存一致) if (realObj!=null&&realMethod!=null){ return realMethod.invoke(realObj,args); }else { return method.invoke(proxy,args); } ~~~ ## 參考資料 [輕松學,Java 中的代理模式及動態代理](https://blog.csdn.net/briblue/article/details/73928350)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看