> scan(String... packages) throws Exception;
```
## **使用**
所以一般情况下,你可以直接这么使用:
```java
// 扫描两个包
Mock.scan("forte.test2.beans", "forte.test1.beans", ...);
// 然后直接获取
Mock.get(Xxxx.class);
// 使用 
```
# **映射代理**
1.6.0版本后,我更新了**映射扫描**与**映射代理**功能。感谢提出建议的朋友。[Issue#I1CCMT](https://gitee.com/ForteScarlet/Mock.java/issues/I1CCMT)
首先看一下Issue上提出的模拟场景:
```java
// interface 
public interface ServiceA{
    VoA methodA();
}
// bean, can with @MockBean
public class VoA{
    @MockValue("@cname")
    private String p1;
}
```
此时,接口中的`methodA()`方法的返回值`VoA`恰好是一个MockBean,这时候,我想要得到`ServiceA`的一个代理对象,使其能够通过`methodA()`得到`VoA`的实例对象。
ok,因此我添加了方法`Mock.proxy(...)`及其重载。方法定义如下:
```java
    /**
     *  为一个接口提供一个代理对象。此接口中,所有的 抽象方法 都会被扫描,假如他的返回值存在与Mock中,则为其创建代理。
     *  此方法默认不会为使用者保存单例,每次代理都会代理一个新的对象,因此如果有需要,请保存一个单例对象而不是频繁代理。
     * @param type    要代理的接口类型。
     * @param factory 接口代理处理器的获取工厂。可自行实现。
     * @param  接口类型
     * @return 代理结果
     */
    public static  T proxy(Class type, MockProxyHandlerFactory factory);
```
此方法传入一个接口类型`Class type` 和一个动态代理处理器`MockProxyHandlerFactory factory`,来获取一个代理对象。
`MockProxyHandlerFactory`是一个接口类型,只存在一个抽象方法:
```java
    /**
     * 获取代理处理接口{@link InvocationHandler}实例
     * @param mockObjectFunction 传入一个类型和一个可能为null的name字符串,获取一个mockObject对象。如果存在name,则会尝试先用name获取
     * @return JDK动态代理所需要的代理处理器示例。
     * @see InvocationHandler
     */
    InvocationHandler getHandler(BiFunction, String, MockObject>> mockObjectFunction);
```
此接口定义了如何创建一个代理类。`InvocationHandler`是JDK为动态代理的创建所提供的一个接口,知道动态代理的人对他应该不会很陌生。
但是如果不熟悉也没关系,我在内部提供了一个默认的实现`MockProxyHandlerFactoryImpl`,同时也为`Mock.proxy(...)`提供了一个重载方法:
```java
    /**
     *  为一个接口提供一个代理对象。此接口中,所有的 抽象方法 都会被扫描,假如他的返回值存在与Mock中,则为其创建代理。
     *  此方法默认不会为使用者保存单例,每次代理都会代理一个新的对象,因此如果有需要,请保存一个单例对象而不是频繁代理。
     *  使用默认的接口代理处理器工厂{@link MockProxyHandlerFactoryImpl}。
     *  默认处理工厂中,代理接口时,被代理的方法需要:
     *  不是default方法。default方法会根据其自己的逻辑执行。
     *  没有参数
     *  没有标注{@code @MockProxy(ignore=true) ignore=true的时候代表忽略}
     * 
     * @see MockProxyHandlerFactoryImpl
     * @param type    要代理的接口类型。
     * @return 接口代理
     */
    public static  T proxy(Class type);
```
因此,一般情况下,你可以直接这么使用:
```java
MockTestInterface proxy = Mock.proxy(MockInterface.class);
```
让我们来创建一个示例接口来看看:
```java
public interface MockTestInterface {
    /**
     * 指定List的泛型类型为User类型,长度为2-4之间
     */
    @MockProxy(size = {2, 4}, genericType = User.class)
    List list();
    /**
     * 默认情况下,长度为1
     */
    Teacher[] array();
    /**
     * 直接获取,不用注解。
     */
    Admin admin();
    
    /**
     * 获取name为{@code mock_map}的mockObject, 基本上返回值都是Map类型。
     */
    @MockProxy(name = "mock_map")
    Map map();
    /**
     * 忽略, 返回值会默认为null
     * @return null
     */
    @MockProxy(ignore = true)
    Admin justNullAdmin();
}
```
可以看到,上面的这些抽象方法中,有一部分方法标注了注解`@MockProxy`。此注解参数如下:
```java
    /**
     *  是否忽略此方法。如果为是,则接口的最终代理结果为返回一个null。
     *  当然,如果获取不到对应的Mock类型,无论是否忽略都会返回null或者默认值。
     *  如果是基础数据类型相关,数字类型,返回{@code 0 或 0.0}。
     *  如果是基础数据类型相关,char类型,返回{@code ' '}。
     *  如果是基础数据类型相关,boolean类型,返回{@code false}。
     */
    boolean ignore() default false;
    /**
     * 如果此参数存在值,则会优先尝试通过name获取MockObject对象。一般应用在返回值为Map类型的时候。
     */
    String name() default "";
    /**
     *  当接口返回值为数组或者集合的时候,此方法标记其返回值数量大小区间{@link [min, max], 即 max >= size >= min}。是数学上的闭区间。
     *  如果此参数长度为0,则返回值为1。
     *  如果参数长度为1,则相当于不是随机长度。
     *  如果参数长度大于2,只取前两位。
     */
    int[] size() default {1,1};
    /**
     *  指定返回值类型,三种可能类型:list类型,array类型,Object其他任意类型。默认值为Unknown类型。当为Unknown类型的时候,会根据返回值类型自动判断。
     *  当类型为list与array类型的时候,需要通过{@link #genericType()}方法指定泛型的类型,获取mock类型的时候将会通过此方法得到的类型来获取。
     */
    MockProxyType proxyType() default MockProxyType.UNKNOWN;
    /**
     * 假如类型为List或者数组类型,此处代表泛型的实际类型。
     */
    Class> genericType() default Object.class;
```
简单汇总一下此注解的参数:
- ignore:忽略这个方法。
- name:指定mockObject的name。一般在返回值为Map类型的时候使用。
- size:指定大小区间。只有在返回值为array或者List类型的时候才有用。
- proxyType:指定返回值类型。一般情况下可以自动推断。
- genericType:当返回值为List类型的时候,此参数指定他的泛型类型。array类型可以进行推断。
  
`@MockProxy`并不是必须的,但也不是可能完全省略的,需要根据实际情况来。一般来讲,如果返回值是一个任意的bean类型,则基本上可以省略,而数组类型如果没有长度要求的话也可以省略,但是例如list、map类型基本上是需要配置部分参数的。
## **使用**
接着上面的`MockTestInterface`,在使用的时候就是这个样子的:
```java
public static void main(String[] args) throws Exception {
        // 扫描包
        Mock.scan("com.test");
        // 注册一个map类型的mockbean
        Mock.set("mock_map", new HashMap(){{
            put("name_map", "@cname");
        }});
        // 获取接口代理
        final MockTestInterface proxy = Mock.proxy(MockTestInterface.class);
        // 输出测试
        System.out.println("proxy.admin(): " + proxy.admin());
        System.out.println("proxy.justNullAdmin(): " + proxy.justNullAdmin());
        System.out.println("proxy.list(): " + proxy.list());
        System.out.println("proxy.array(): " + Arrays.toString(proxy.array()));
        System.out.println("proxy.map(): " + proxy.map());
}
```
# #函数
(v1.7.0更新,参阅wiki `8_#function&class parse`)
# List区间(v1.7.0)
(v1.7.0更新,参阅wiki `9_List interval parameter(v1.7.0)`)
## **注意事项**
- 尽可能别用泛型。
- 每次使用`Mock.proxy(...)`都会去生成动态代理对象,会影响性能,所以尽可能保存成一个单例使用。
# **使用依赖列表**
```xml
   commons-beanutils
   commons-beanutils
   1.9.3
```
## 更新公告
### **v1.9.2(2020/10/24)**
- 追加一个区间参数`const`, 当区间参数为 `const`的时候,将不会对value值进行解析,而是直接原样赋值。
`const`区间参数常用于对`Map`类型的`MockObject`的某些字段指定默认值。
例如:
```java
        Map map = new HashMap<>();
        // 区间参数为 'const'
        map.put("dataLevel|const", new int[]{51, 52, 53});
        Mock.set("usermap", map);
        MockObject