Jdk动态代理

代理模式的本质:监控行为特征
JDK动态代理实现
1.接口角色:定义所有需要被监听行为
2.接口实现类:定义实现被监听对象
3.通知类:
1)对次要业务进行具体实现
2)通知JVM,当前被拦截的主要业务方法与次要业务方法应该如何绑定
4.监控对象(代理对象)
1)被监控实例对象
2)需要被监控的行为
3)具体通知类实例对象
代码实现

1.定义一个要监控的行为—>接口

public interface Eat {
    /**
     * 某种生物吃东西
     * @param something
     */
    void eat(String something);
}

2.定义实现接口的实例

public class Person implements Eat {
    @Override
    public void eat(String something) {
        System.out.println("我吃" + something);
    }
}

3.通知jvm需要拦截的方法—>实现InvocationHandler

public class Invocation implements InvocationHandler {

public Invocation(Object object) {
    this.object = object;
}

    private Object object;
    
    /***
     *  这个方法就是要告诉代理对象要处理的方法
     *
     *  @param proxy 代理对象
     *  @param method    实例对象要调用的方法
     *  @param args  实例对象要调用的方法的参数
     *  @return  Object
     *  @throws Throwable
     */    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (object instanceof Person){
            wash();
        }else if(object instanceof Dog){
            sound();
        }
        return method.invoke(object, args);
    }
    private void wash(){
        System.out.println("我是人,我要洗手");
    }
    private void sound(){
        System.out.println("我是狗,汪汪汪");
    }
}

4.创建代理对象

public static Object getInstance(Class clz) throws IllegalAccessException, InstantiationException {

    /**
     *
     *  ClassLoader loader, 被代理类的加载器
     *  Class<?>[] interfaces,  被代理类的所有接口
     *  InvocationHandler h 调用的处理器
     *  
     *  return 代理对象
     */
    Object object = Proxy.newProxyInstance(clz.getClassLoader(), clz.getInterfaces(), new Invocation(clz.newInstance()));
    return object;
}
Proxy.newProxyInstance方法解析
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{
    //判断InvocationHandler对象是否为空
    Objects.requireNonNull(h);
    //获取接口的克隆对象
    final Class<?>[] intfs = interfaces.clone();
    //获取安全管理对象,一般为空
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }

    //通过类加载器和接口去找或者生成接口对应的代理类
    Class<?> cl = getProxyClass0(loader, intfs);

    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }

        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
        return cons.newInstance(new Object[]{h});
    } catch (IllegalAccessException|InstantiationException e) {
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
        Throwable t = e.getCause();
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new InternalError(t.toString(), t);
        }
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString(), e);
    }
}
//解析真正获取代理对象的方法
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }
    //这里似乎是从缓存中拿到了数据,继续往下看
    return proxyClassCache.get(loader, interfaces);
}
// proxyClassCache.get(loader, interfaces)
public V get(K key, P parameter) {
    //判断接口是否为空
    Objects.requireNonNull(parameter);
    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey =
    Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                supplier = factory;
            }
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
JDK动态代理特点
1.实现InvocationHandlder接口
2.通过Proxy.newProxyInstance方法创建代理对象
3.被代理的对象必须实现接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值