文章目录

  • 01 代理
    • 1.1 什么是代理?
    • 1.2 为什么要找中介
  • 02 静态代理
    • 2.1 使用代理模式的作用
    • 2.2 实现代理的方式
    • 2.3 具体实现
    • 2.4 静态代理的优缺点
  • 03 动态代理
    • 3.1 静态代理和动态代理模式的对比
    • 3.2 动态代理的介绍
    • 3.3 回顾反射 Method类
      • 3.3.1 class.getMethod
      • 3.3.2 Method.invoke
    • 3.4 JDK动态代理
      • 3.4.1 Interface InvocationHandler
      • 3.4.2 Method
      • 3.4.3 Proxy类
    • 3.5 JDK动态代理实现步骤
    • 3.6 静态代理的优缺点
  • 04 实现动态代理的步骤
  • 05 JDK动态代理执行流程
  • 06 静态代理项目中的应用
  • 07 完结

01 代理

1.1 什么是代理?

代理,在我们日常生活之中就有体现,代购,中介,换ip,商家等等.

比如有一家美国的大学,可以对全世界招生.留学中介(代理 )

留学中介(代理):帮助这家美国的学校招生,中介是学校的代理中介是代替学校完成招生功能

代理特点

  1. 中介和代理他们要做的事情是一致的:招生
  2. 中介是学校代理,学校是目标
  3. 家长-------->中介(学校介绍,办理入学手续)---------->美国学校
  4. 中介是代理,收取费用

1.2 为什么要找中介

1.中介是专业的,方便.
2.家长现在不能自己去找学校。家长没有能力访问学校.或者美国学校不接收个人来访

买东西都是商家卖, 商家是某个商品的代理, 你个人买东西,肯定不会让你接触到厂家的.

02 静态代理

2.1 使用代理模式的作用

  1. 功能增强:在你原有的功能上,增加了额外的功能.新增加的功能,叫做功能增强
  2. 控制访问:代理类不让你访问目标,例如商家不让用户访问厂家

2.2 实现代理的方式

1)代理类是自己手工实现的,自己创建一个java类,表示代理类
2)同时你所要代理的目标

特点:
1)实现简单
2)容易理解

模拟一个用户购买u盘的行为。
用户:客户端类
商家:代理,代理某个品牌的u盘。
厂家:目标类。
三者的关系:用户(客户端)-—-商家(代理)-—-厂家(目标)
商家和厂家都是卖u盘的,他们完成的功能是一致的,都是卖u盘。

实现步骤:

实现步骤
1.创建一个接口,定义卖u盘的方法,表示你的厂家和商家做的事情
2.创建厂家类,实现1步骤的接口
3.创建商家,就是代理,也需要实现1步骤中的接口
4.创建客户端类,调用商家的方法买一个u盘

2.3 具体实现

实现步骤
1.创建一个接口,定义卖u盘的方法,表示你的厂家和商家做的事情

package com.rango.service;
public interface usbSell {/*** 定义一个方法 参数 amount:表示一次购买的数量,暂时不用* 返回值表示一个u盘的价格* @param amount* @return*/float sell(int amount);
}

2.创建厂家类,实现1步骤的接口

package com.rango.factory;import com.rango.service.usbSell;
//目标类:金士顿厂家,不接受用户的单独购买
public class UsbKingFactory implements usbSell {/*** 定义一个方法 参数 amount:表示一次购买的数量,暂时不用* 返回值表示一个u盘的价格** @param amount* @return*/@Override
//一个128G的U盘是85元.
//    后期根据amount,可以实现不同的价格,例如10000个,单击是80,50000个75public float sell(int amount) {return 85.0f*amount;}
}

3.创建商家,就是代理,也需要实现1步骤中的接口

package com.rango.business;import com.rango.factory.UsbKingFactory;
import com.rango.service.usbSell;//淘宝是一个商家,代理金士顿U盘的销售
public class TaoBao implements usbSell {//      声明 商家代理的厂家具体是谁private UsbKingFactory factory =new UsbKingFactory();@Override
//    实现销售U盘功能public float sell(int amount) {//        向厂家发送订单,告诉厂家,我买了U盘,厂家发货
//        发送给工厂,我需要的订单,返回报价float price = factory.sell(amount);
//        商家需要加价也就是代理要增加价格price = price + 25;
//在目标类的方法调用后,你做的其他功能,都是增强的意思System.out.println("淘宝再给你返回一个优惠券,或者红包");
//        增加的价格return price;}
}

4.创建客户端类,调用商家的方法买一个u盘

import com.rango.business.TaoBao;public class shopMain {public static void main(String[] args){//             创建代理的商家淘宝对象TaoBao taoBao = new TaoBao();
//        我只向淘宝买一件产品,得到报价float price = taoBao.sell(2);System.out.println("购买一件产品.淘宝的报价为: "+price);}
}

代理类完成的功能:

  1. 目标类中方法的调用
  2. 功能增强

所属我们只有一个代理商,我们实际上可以写多个代理商,

2.4 静态代理的优缺点

优点:

  1. 实现简单
  2. 容易简单

确定:当你的项目中,目标类的代理类很多的时候,有以下的缺点

  1. 当目标类增加了,代理类可能也需要成倍的增加
  2. 当你的接口中功能在增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要修改,影响比较多.

03 动态代理

1)什么是动态代理?

使用jdk的反射机制,创建对象的能力,创建的是代理类的的对象.而不用我们创建类文件,不用写java文件, 什么叫动态?在程序执行时,调用jdk提供的方法才能创建代理类的对象

3.1 静态代理和动态代理模式的对比

在静态代理中目标很多的时候,可以使用动态代理,避免静态代理的缺点

在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点。
动态代理中目标类即使很多,

  1. 代理类数量可以很少,
  2. 当你修改了接口中的方法时,不会影响代理类。

动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。

换句话说:动态代理是一种创建java象的能力,让你不用创建 TaoBao类就能创建代理类对象,除去了中间商

在java中,要想创建对象

  1. 创建类文件,java 文件编译为class
  2. 使用构造方法,创建类的对象

3.2 动态代理的介绍

  1. 动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的,java源文件。
  2. 动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。
  3. 动态代理的实现方式常用的有两种:使用JDK代理,与通过CGLlB动态代理。

动态代理的实现:

  1. jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
  2. cglib动态代理(了解): cglib是第三方的工具库,创建代理对象
    1. cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中
      重写父类中同名的方法,实现功能的修改。
    2. 因为cglib是继承,重写方法,所以要求目标类不能是fina1的,方法也不能是final的。cglib的要求目标类比较宽松,只要能继承就可以了。cglib在很多的框架中使用,
      比如mybatis,spring框架中都有使用。
package Test;import com.rango.Impl.HelloServiceImpl;
import com.rango.service.HelloService;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class TestApp {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//        HelloService service = new HelloServiceImpl();
//        service.sayhello("张三");
//        以上是常规方法执行sayhello
//        下面我们使用反射机制进行创建sayhello方法,核心Method(类中的方法)HelloServiceImpl target = new HelloServiceImpl();
//        获取sayhello名称对应的Method类对象
//         public Method getM   ethod(String name, Class<?>... parameterTypes)
//        加入,该方法的参数有多个该怎么办?
//        parameterTypes参数是一个类对象数组,按声明的顺序标识方法的形式参数类型。Method method = HelloService.class.getMethod("sayhello", String.class);
//        通过Metho可以执行sayhello方法的调用/**  public Object invoke(Object obj, Object... args)*       表示执行方法的调用*   参数:*       1.Object,表示对象,要执行这个对象的方法*       2.Object...args,方法执行时的参数值* 返回值:*       Object:方法执行后的返回值* */Object ret = method.invoke(target, "李四");}
}

3.3 回顾反射 Method类

Method类的结构图

  • Class Method

    • java.lang.Object

      • java.lang.reflect.AccessibleObject

        • java.lang.reflect.Executable

          • java.lang.reflect.Method

3.3.1 class.getMethod

Method method = HelloService.class.getMethod("sayhello", String.class,Integer.class);

提出问题?

    public Method getMethod(String name, Class<?>... parameterTypes)

加入该方法的参数有多个该怎么办?
parameterTypes参数是一个类对象数组,按声明的顺序标识方法的形式参数类型。

3.3.2 Method.invoke

public Object invoke(Object obj,Object... args)
*  public Object invoke(Object obj, Object... args)
*       表示执行方法的调用
*   参数:
*       1.Object,表示对象,要执行这个对象的方法
*       2.Object...args,方法执行时的参数值
* 返回值:
*       Object:方法执行后的返回值
*

3.4 JDK动态代理

jdk动态代理:
1.反射, Method类,表示方法。类中的方法。通过Method可以执行某个方法

2.jdk动态代理的实现
反射包java.lang. reflect,里面有三个类:InvocationHandler,Method,Proxy

3.4.1 Interface InvocationHandler

public interface InvocationHandler

InvocationHandler是由代理实例的调用处理程序实现的接口 。
每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

1)InvocationHandler接口(调用处理器):就一个方法 invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在
invoke()方法中。

代理类完成的功能1.调用目标方法,执行目标方法的功能2.功能增强,在目标方法调用时,增加功能

方法原型:

参数:object proxy:jdk创建的代理对象,无需赋值。Method method:目标类中的方法,jdk提供method对象的object[]args:目标类中方法的参数,jdk提供的。
Object invoke(Object proxy,方法 method,Object[] args)throws Throwable处理代理实例上的方法调用并返回结果。

3.4.2 Method

2)Method类:表示方法的,确切的说就是目标类中的方法。
作用:通过 Method可以执行某个目标类的方法, Method. invoke();
method. invoke(目标对象,方法的参数)

object ret= method. invoke(service22,"李四")

说明:method.invoke()就是为了用来执行目标方法的,等同于静态代理中的

   //        向厂家发送订单,告诉厂家,我买了U盘,厂家发货//        发送给工厂,我需要的订单,返回报价float price = factory.sell(amount);

3.4.3 Proxy类

3)proxy类:核心的对象,创建代理对象。之前创建对象都是new类的构造方法()
现在我们是使用proxy类的方法,代替new的使用。
方法:静态方法 newProxyInstance()
作用是:创建代理对象,等同于静态代理中的TaoBao taoBao=new TaoBao()

我们来观察方法原型

    public static Object newProxyInstance( ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)   throws IllegalArgumentException

参数:

  1. ClassLoader loader 类加载器,负责向内存中加载对象的,使用反射机制获取对象的classLoader,

如何获取? 类 a, a.getCalss().getClassLoader(),目标对象的类加载器

这里我们细分:每一个类都继承Object类,在Object中有一个getClass方法,表示 类对象的运行时类的Class对象。 而Class类里面有一个public ClassLoader getClassLoader()方法

  1. Class<?>[] interfaces: 接口,目标对象实现的接口,也是反射获取的
  2. InvocationHandler h : 我们自己写的,代理类要完成的功能

返回值也就是代理对象

3.5 JDK动态代理实现步骤

实现步骤
1.创建一个接口,定义卖u盘的方法,表示你的厂家和商家做的事情

package com.rango.service;
public interface usbSell {/*** 定义一个方法 参数 amount:表示一次购买的数量,暂时不用* 返回值表示一个u盘的价格* @param amount* @return*/float sell(int amount);
}

2.创建厂家类,实现1步骤的接口

package com.rango.factory;import com.rango.service.usbSell;
//目标类:金士顿厂家,不接受用户的单独购买
public class UsbKingFactory implements usbSell {/*** 定义一个方法 参数 amount:表示一次购买的数量,暂时不用* 返回值表示一个u盘的价格** @param amount* @return*/@Override
//一个128G的U盘是85元.
//    后期根据amount,可以实现不同的价格,例如10000个,单击是80,50000个75public float sell(int amount) {return 85.0f*amount;}
}

3.创建商家,就是代理,也需要实现1步骤中的接口

package com.rango.business;import com.rango.factory.UsbKingFactory;
import com.rango.service.usbSell;//淘宝是一个商家,代理金士顿U盘的销售
public class TaoBao implements usbSell {//      声明 商家代理的厂家具体是谁private UsbKingFactory factory =new UsbKingFactory();@Override
//    实现销售U盘功能public float sell(int amount) {//        向厂家发送订单,告诉厂家,我买了U盘,厂家发货
//        发送给工厂,我需要的订单,返回报价float price = factory.sell(amount);
//        商家需要加价也就是代理要增加价格price = price + 25;
//在目标类的方法调用后,你做的其他功能,都是增强的意思System.out.println("淘宝再给你返回一个优惠券,或者红包");
//        增加的价格return price;}
}

4.创建客户端类,调用商家的方法买一个u盘

import com.rango.business.TaoBao;public class shopMain {public static void main(String[] args){//             创建代理的商家淘宝对象TaoBao taoBao = new TaoBao();
//        我只向淘宝买一件产品,得到报价float price = taoBao.sell(2);System.out.println("购买一件产品.淘宝的报价为: "+price);}
}

所以我们再次总结代理类完成的功能:

  1. 目标类中方法的调用
  2. 功能增强

所属我们只有一个代理商,我们实际上可以写多个代理商,

3.6 静态代理的优缺点

我们再次总结一下静态代理的优缺点

优点:

  1. 实现简单
  2. 容易简单

确定:当你的项目中,目标类的代理类很多的时候,有一下的缺点

  1. 当目标类增加了,代理类可能也需要成倍的增加
  2. 当你的接口中功能在增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要修改,影响比较多.

所以我们继续学习动态代理

04 实现动态代理的步骤

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  4. 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型

第一步:创建接口,定义目标所需功能

public interface UsbSell {float sell(int amount);
}

第二步:创建目标类实现接口

public class UsbKingFactory implements UsbSell {@Overridepublic float sell(int amount) {System.out.println("目标类中,执行了sell目标方法");return 85.02f;}
}

我们写了接口类,定义了功能,写了代理类,实现了接口功能,按照以前的操作,现在就需要写一个真正的代理类,创建对象.

第三步: 创建Invocationhandler实现类.在invoke()方法中完成代理类的对象

1.调用目标的方法

2.增强功能

public class MyHandle implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;}
}

我们就在以前代理类的实现方法上进行修改

//之前的代理类public class TaoBao implements usbSell {//      声明 商家代理的厂家具体是谁private UsbKingFactory factory =new UsbKingFactory();@Override//    实现销售U盘功能public float sell(int amount) {//        向厂家发送订单,告诉厂家,我买了U盘,厂家发货//        发送给工厂,我需要的订单,返回报价float price = factory.sell(amount);//        商家需要加价也就是代理要增加价格price = price + 25;//在目标类的方法调用后,你做的其他功能,都是增强的意思System.out.println("淘宝再给你返回一个优惠券,或者红包");//        增加的价格return price;}}

调用目标的方法

//传入是谁的对象,就给谁创建代理public MyHandle(Object target) {this.target = target;}
invoke里面的设置Object res =null;//        向厂家发送订单,告诉厂家,我买了U盘,厂家发货//        发送给工厂,我需要的订单,返回报价
//            float price = factory.sell(amount);res = method.invoke(target,args);       //待执行目标方法,执行后返回值

第四步: 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型

创建一个MainShop类.

public class MainShop {public static void main(String[] args){
//            1.创建对象,使用Proxy
//            2.创建目标对象UsbSell factory = new UsbKingFactory();
//        3.创建Invocationhandler对象InvocationHandler myHandle = new MyHandle(factory);//        4.创建代理对象UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),myHandle);
//        通过代理执行方法float price = proxy.sell(1);System.out.println("通过动态代理对象,调用方法:" +price);}
}

执行成功.和之前动态代理模式一样

05 JDK动态代理执行流程

Proxy类,实现动态代理的流程,使用返回指定接口的代理类实例,

我们此时debug一下程序,在invok实现类中打一个断点
此时我们再观察,代理对象MyHandler里面的invoke方法的参数

06 静态代理项目中的应用

我们需要知道代理能做什么?

在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码,程序开发中的意思,

比如:你所在的项目,有一个功能是其他人(公司其他部门,其他小组的人)写好的,你可以使用

//比如,同事开发一个GoNong类
GoNong.class ,
GoNong gn=new GoNong()//我们需要增加一个print方法

我们发现这个功能现在还存在缺点,不能完全满足我项目的需要,我需要在print()执行过后,需要自己再增加代理,使用什么方法那,肯定是代理,因为别人不会让我们看源文件

执行步骤:

  1. 我们先建立一个接口功能,很简单的一个功能
public interface HelloService {/*** 打印报表,报表* @param name* @return*/int print (String name);
}
  1. 我们再加个接口实现类
public class GoNeng implements HelloService {@Overridepublic int print(String name) {System.out.println("其他人写好的这个方法!");return 2;}
}
  1. 我们如果相对上述功能进行修改,我们不可能直接去在原方法上进行修改

我们设置一个类来使用这个接口

public class MyApp {public static void main(String[] args){GoNeng gn = new GoNeng();int i = gn.print("nihao1");System.out.println("num" +i);}
}

问题是如果我们想修改这个功能改怎么办?在不修改源代码的基础上,我们可以创建一个代理类,来增强这个类方法,

  1. 设置一个代理类实现功能的增强和代理
public class MyInvocationHandler implements InvocationHandler {private Object target=null;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//        调用目标方法,执行print()得到2Object res  =  method.invoke(target,args);  //返回为2的结果//我们可以把结果再乘以2if (res!=null){Integer num  = (Integer) res;res = num*2; }return null;}
}
  1. 我们仍回到主方法里面进行测试
public class MyApp {public static void main(String[] args){//        GoNeng gn = new GoNeng();
//        int i = gn.print("nihao1");
//        System.out.println("num" +i);GoNeng goNeng = new GoNeng();InvocationHandler handler = new MyInvocationHandler(goNeng);HelloService proxy = (HelloService) Proxy.newProxyInstance(goNeng.getClass().getClassLoader(), goNeng.getClass().getInterfaces(),handler);int num = proxy.print("市场");System.out.println("我们期望得到的 num =="+num);}
}

测试System.out.println("动态代理类参数接口"+goNeng.getClass().getInterfaces()[0].getName());

动态代理类参数接口com.rango.service.HelloService
其他人写好的这个方法!
我们期望得到的 num ==4

07 完结

动态代理,必须要有接口出现,如果没有,我们可以使用cglib实现

23种设计模式——JDK动态代理(AOP)相关推荐

  1. Spring 面向切面编程 第3关:AOP实现原理-JDK动态代理

    目录 任务描述 相关知识 代理模式(Proxy) AOP实现的两种方式 JDK动态代理步骤 案例模拟AOP实现 代理类说明 编程要求 测试说明 参考代码 任务描述 我们知道,Spring AOP的主要 ...

  2. Jdk动态代理 底层源码分析

    前言 java动态代理主要有2种,Jdk动态代理.Cglib动态代理,本文主要讲解Jdk动态代理的使用.运行机制.以及源码分析.当spring没有手动开启Cglib动态代理,即:<aop:asp ...

  3. 谁与争锋,JDK动态代理大战CGLib动态代理

    文章目录 一.前言 二.基本概念 三.JDK 和 CGLib动态代理区别 3.1 JDK动态代理具体实现原理 3.2 CGLib动态代理 3.3 两者对比 3.4 使用注意 四.JDK 和 CGLib ...

  4. Java设计模式-----Cglib动态代理(Cglib Proxy)

    接上文:4.2Java设计模式-----JDK动态代理(Dynamic Proxy) Cglib动态代理 百度百科:Cglib是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java ...

  5. Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理

    前言 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 很多人至今都是看到 代理就懵, 静态代理.动态代理.JDK动态代理.CGL ...

  6. aop的四种增强以及JDK动态代理、Cglib动态代理

    动态代理 AOP底层实现:有接口自动应用的就是JDK动态代理 (1).JDK 在运行时运行时注入 本质:在内存中构建出接口的实现类 特点:被代理对象,必须有接口 实例: import java.lan ...

  7. 23种设计模式之代理模式(动态代理)

    代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式的组成 抽 ...

  8. 23种设计模式之代理模式

    文章目录 代理模式的定义与特点 代理模式的结构与实现 模式的结构 模式的实现 代理模式的应用场景 代理模式的应用实例 代理模式的扩展 代理模式分类 静态代理 动态代理 在有些情况下,一个客户不能或者不 ...

  9. Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理

    文章目录 什么是代理模式 代理模式应用场景 代理的分类 静态代理 什么是静态代理 深入解析静态代理 小结 动态代理 什么是动态代理 JDK动态代理 原理和实现方式 代码实现 优缺点 Cglib动态代理 ...

最新文章

  1. echarts grid的样式位置_ECharts grid组件配置 提示框浮层的位置
  2. (59)Linux操作系统深入应用
  3. recycleview 嵌套高度问题_简单解决RecyclerView嵌套的RecyclerView条目显示不全和宽度不能铺满...
  4. 教你如何用Harbor 私有镜像仓库搭建
  5. Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
  6. 关于神经网络的需要注意的概念总结
  7. Mac下配置Android环境
  8. Python提示ModuleNotFoundError: No module named ‘PIL‘,已解决
  9. NPM ---- 安装yarn
  10. 高等数学-不定积分基本公式
  11. 汽车UDS诊断详解及Vector相关工具链使用说明——总述
  12. windows设置定时自动关闭应用
  13. Python数据可视化Matplotlib学习
  14. 日知录(七):python之理解pygame飞机大战
  15. ETL讲解(很详细!!!)
  16. c语言入门自学免费app,C语言入门学习最新版下载-C语言入门学习app手机版v1.0.2 安卓版-腾飞网...
  17. Dev-C++ 的下载、安装和配置
  18. 自由 Freedom
  19. 【NI Multisim 14.0原理图设计基础——元器件分类】
  20. MAC系统 LightGBM模型转为pmml格式

热门文章

  1. 物联网卡会锁卡吗_4G物联网监控摄像机为什么要用物联网卡?
  2. 【2021】网络协议从入门到底层原理-MJ【新】附上下载链接
  3. 关于技术博客--找工作--这些年--陆续的
  4. 苹果三代耳机_airpods三代上市时间 苹果第三代蓝牙耳机什么时候上市
  5. 根据入栈顺序判断出栈顺序的合法性
  6. MIT-BIH介绍(二)什么是MIT-BIH?
  7. Python3全面基础学习
  8. 夏普中国否认出售电视业务:中国市场是核心阵地
  9. Yield Guild Games 和 MOBLAND 达成合作
  10. 21级pta《查找表》