文章目录
一、 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)
}