动态代理的介绍

一、 Java 动态代理

1. 动态代理Demo

// java.lang.reflect.InvocationHandler
public interface InvocationHandler {
    Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
}
// 接口定义
public interface UserInterface{
    void sayHello();
}

// 真实角色
public class User implements UserInterface{
    @Override
    public void sayHello(){
        System.out.println("Hello World");
    }
}

// 处理类
public class UserHandler implements InvocationHandler{
    private User user;
    public UserProxy(User user){
        this.user = user;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[]args) throws Throwable{
        System.out.println("invoking start...");
        // method --> sayHello()
        method.invoke(user);
        System.out.println("invoking end...");
        return user;
    }
}
// 执行类
public class Main{
    public static void main(String [] args){
        User user = new User();
        UserHandler userHandler = new UserHandler(user);
        // 开启将代理类class文件保存到本地模式,一般不会用
        System.getProperties().put("sum.misc.ProxyGenerator.saveGeneratedFiles","true");
        // 动态代理生成代理对象$Proxy0
        Object o = Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{UserInterface.class}, userHandler);
        ((UserInterface)o).sayHello();
    }
}
/*
invoking start...
Hello World
invoking end...
*/

2. 代理模式

简单捋一捋代理模式实现原理:真实角色和代理角色共同实现一个接口并实现抽象方法A,代理类持有真实角色对象,代理类在A方法中调用真实角色对象的A方法。在Main中实例化代理对象,调用其A方法,间接调用了真实角色的A方法

// 静态代理类
public class UserProxy implements UserInterface{
    private User user = new User();
    
    @Override
    public void sayHello(){
        System.out.println("invoking start...");
        user.sayHello();
        System.out.println("invoking end...")
    }
}

// 执行类
public class Main{
    public static void main(String[]args){
        UserInterface userProxy = =new UserProxy();
        userProxy.sayHello();
    }
}

3. 猜想的动态代理类

和 Demo 中的动态代理做比较,区别是动态代理实现的是InvocationHandler,静态代理实现的是UserInterface。对比它们的invoke()sayHello()方法,发现代码是一模一样的。我们通过修改一下UserProxy类,将静态代理改为动态代理

// 动态代理是:com.sun.proxy.$Proxy0,下面这个是我们的动态代理实现类
public class UserProxy implements UserInterface{
    private InvocationHandler handler;
    public UserProxy(InvocationHandler handler){
        this.handler = handler;
    }
    @Override
    public void sayHello(){
        try{
            handler.invoke(this, UserInterface.class.getMethod("sayHello"),null);
        }catch(Throwable throwable){
            throwabel.printStackTrace();
        }
    }
}

// 执行类
public class Main{
    public static void main(String[]args){
        User user = new User();
        UserHandler userHandler = new UserHandler(user);
        UserProxy proxy = new UserProxy(userHandler);
        proxy.sayHello();
    }
}
/*
invoking start...
Hello World
invoking end...
*/

上面的代码是写死的,而动态代理是当我们调用Proxy.newProxyInstance(loader,interfaces,h)时,会根据传入的参数来动态生成这个代理类代码

二、 源码分析

// \java\lang\reflect\Proxy.java
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvvocationHandler h){
	//...
    Class<?> cl = getProxyClass0(loader, intfs);
    //...
}

private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }

    // If the proxy class defined by the given loader implementing
    // the given interfaces exists, this will simply return the cached copy;
    // otherwise, it will create the proxy class via the ProxyClassFactory
    return proxyClassCache.get(loader, interfaces);
}

1. WeakCache

弱引用缓存,WeakReference为弱引用类,用来包装其它对象,在进行GC时,其中包装对象会被回收,而WeakRefrence对象会被放到引用队列中,没有触发GC,引用队列没有weakreference对象

public void test(){
    String s1 = new String("hello");
    
    ReferenceQueue referenceQueue = new ReferenceQueue();
    WeakReference<String> s2 = new WeakReference<>(new String("world"), referenceQueue);
    
    System.gc();
    Thread.sleep(3);
    
    System.out.println(s2.get());
    System.out.println(referenceQueue.poll());
}
/*
null
java.lang.ref.WeakReference@380fb434

未触发GC,则为:
world
null
*/

WeakCache的核心是其成员变量map,它是一个ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>>二级缓存,对应动态代理则是<类加载器,<接口Class,代理Class>>

final class WeakCache<K,P,V>{
    // 存放GC后的弱引用
    private final ReferenceQueue<K> refQueue = new ReferenceQueue<>();
   
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();
    // 可以不关注,标识二级缓存的value是否被回收,即Supplier是否被回收
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>();
    // 包装接口class,生成二级缓存的key
    private final BiFunction<K, P, ?> subKeyFactory;
    // 包装$Proxy0,生成二级缓存的value
    private final BiFunction<K, P, V> valueFactory;
    
    /*
    * 构造方法
    */
    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                     BiFunction<K, P, V> valueFactory) {
        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
        this.valueFactory = Objects.requireNonNull(valueFactory);
    }
    
    /**
    * key:类加载器
    * parameter:接口class
    */
    public V get(K key, P parameter){
        // 将key包装成弱引用
        Object cacheKey = CacheK.valueOf(key, refQueue);
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        if(valuesMap==null){
            // 这时候的结构就是ConCurrentMap<CacheKey, ConcurrentMap<Object, Supplier>)
            ConcurrentMap<Object,Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>());
            // 如果其它线程已经创建了,则直接复用
            if(oldValuesMap!=null){
                valuesMap = oldValuesMap;
            }
        }
	    // 看下面<生成二级缓存的key>,
        // 此时 map 的结构就是ConCurrentMap<CacheKey, ConCurrentMap<subKey,Supplier>>
        Object subKey = subkeyFactory.apply(key, parameter);
        // 根据二级缓存的subKey获取value
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;
        // 直到完成二级缓存Value的构建才结束,Value是弱引用的$Proxy0.class!!!
        while(true){
            // 第一次循环:suppiler肯定是null,因为还没有将放入二级缓存的KV值
           // 第二次循环:这里suppiler不为null了!!!进入if
           if (supplier != null) {
                // 第二次循环:真正生成代理对象,
                // 往后翻,看<生成二级缓存Value>,核心!!!!!
                // 看完后面回到这里:value就是弱引用后的$Proxy0.class
                V value = supplier.get();
                if (value != null) {
             // 本方法及上部分的最后一行代码,跳转最后的<构建$Proxy对象>
                    return value;
                }
               // 第一次循环:factory肯定为null,生成二级缓存的Value
                if (factory == null) {
                    factory = new Factory(key, parameter, subKey, valuesMap);
                }
             	// 第一次循环:将subKey和factory作为KV放入二级缓存
                if (supplier == null) {
                    supplier = valuesMap.putIfAbsent(subKey, factory);
                    	if (supplier == null) {
                       	 // 第一次循环:赋值之后suppiler就不为空了,记住!!!!!
                      	  supplier = factory;
                    	}
                	} 
           		}
            } 
        }
    }
}

2. 生成二级缓存的key

public interface BiFunction<T, U, R> {
     R apply(T t, U u);
}

public class Proxy implements java.io.Serializable {
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
    
    /**
    * key:类加载器
    * parameter:接口class
    * Object subKey = subkeyFactory.apply(key, parameter);
    */
    private static final class KeyFactory
        implements BiFunction<ClassLoader, Class<?>[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
            switch (interfaces.length) {
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }
}

不管是Key1、Key2、KeyX,都是WeakRefefrence

3. 生成二级缓存value

public interface Supplier<T> {
    T get();
}

final class WeakCache<K,P,V>{
    private final class Factory implements Supplier<V> {
        //...
        @Override
        public synchronized V get() { // serialize access
            V value = null;
            try {
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { // remove us on failure
                    valuesMap.remove(subKey, this);
                }
            }
            //...
            return value;
        }
    }
}

public class Proxy implements java.io.Serializable {
    /**
    * V value = supplier.get();
    * V value = valueFactory.apply(key, parameter);
    */
    private static final class ProxyClassFactory
    	implements BiFunction<ClassLoader, Class<?>[], Class<?>>{
        private static final String proxyClassNamePrefix = "$Proxy";
        
        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
            //...
            String proxyName = proxyPkg + proxyClassNamePrefix + num;
            // class文件写入本地,Android这里使用native去实现,不深究了
            return generateProxy(proxyName, interfaces, loader, methodsArray,
                                     exceptionsArray);
        }
    }
}

4. 构建$Proxy对象

// \java\lang\reflect\Proxy.java
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvvocationHandler h){
	//...
    Class<?> cl = getProxyClass0(loader, intfs);
    final Constructor<?> cons = cl.getConstructor(constructorParams);
    final InvocationHandler ih = h;
    if (!Modifier.isPublic(cl.getModifiers())) {
        cons.setAccessible(true);
    }
    return cons.newInstance(new Object[]{h});
}

cl就是上面获取的二级缓存value -Proxy0.class,通过传入InvocationHandler创建动态代理对象,通过动态代理对象调用sayHello方法,相当于调用InvocationHandler的invoke方法

三、 Android中的运用

先定义三个注解

/**
* 用来代替 Activity.findViewById 方法
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
    int value();
}
/**
* 作用于注解的注解,作用于下面的onClick注解的@EventType注解
*/
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {
    Class listenerType();
    String listenerSetter();
    String methodName();
}
/**
* 替代 View.setOnClickListener 方法
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType=View.OnClickListener.class, listenerSetter="setOnClickListener", methodName="onClick")
public @interface onClick {
    int[] value();
}

反射注解并解析

public class Utils {
    public static void inject(Activity act) {
        Class<?extends Activity> actCls = act.getClass();
        Field[] declaredFields = actCls.getDeclaredFields();
        for (Field f : declaredFields) {
            if (f.isAnnotationPresent(InjectView.class)) {
                InjectView annotation = f.getAnnotation(InjectView.class);
                int value = annotation.value();
                try {
                    Method method = actCls.getMethod("findViewById", int.class);
                    method.setAccessible(true);
                    method.invoe(act, value);
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        Method[] declaredMethods = actCls.getDeclaredMethods();
        for (Method m : declaredMethods) {
            if (m.isAnnotationPresent(onClick.class)) {
                onClick annotation = m.getAnnotation(onClick.class);
                int value = annotation.value();
                // 获取注解的注解
                EventType et = annotation.annotationType().getAnnotation(EventType.class);
                Class listenerType = et.listenerType();
                String listenerSetter = et.listenterSetter();
                String methodName = et.methodName();
                
                // 创建InvocationHandler和动态代理
                ProxyHandler proxyHandler = new ProxyHandler(act);
                Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, proxyHandler);
     
                try {
                  for (int id : value) {
                    //找到Button
                    Method find = activityClass.getMethod("findViewById", int.class);
                    find.setAccessible(true);
                    View btn = (View) find.invoke(activity, id);
                    //根据listenerSetter方法名和listenerType方法参数找到method
                    Method setMethod = btn.getClass().getMethod(listenerSetter, listenerType);
                    setMethod.setAccessible(true);
                    setMethod.invoke(btn, listener);
                }
 
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

看一下InvocationHandler实现

// 处理类
public class ProxyHandler implements InvocationHandler{
    private Activity act;
    public ProxyHandler(Activity act){
        this.act = act;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[]args) throws Throwable{
        method.invoke(act);
        return user;
    }
}

再看看使用

@InjectView(R.id.bt)
Button bt;

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    Utils.inject(this);
}

@onClick(R.id.bt)
public void invokeClick(View v) {
    L.i(TAG, v)
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值