红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25)
关于代理模式我之前有过相关的介绍:
https://blog.csdn.net/u011109881/article/details/82848719
里面介绍了各种代理模式使用的情况
静态代理demo
接口类
public interface IBank {
// 申请银行卡
void applyBank();
// 挂失
void loseBank();
}
代理类
// 银行业务员 代理类
public class BusinessMan implements IBank{
private final IBank mConsumer;
public BusinessMan(IBank man){
this.mConsumer = man;
}
@Override
public void applyBank() {
//申请银行卡
if(mConsumer != null){
Log.e("hjcai","进行挂号等基础流程");
mConsumer.applyBank();
Log.e("hjcai","流程结束");
}
}
// 申请挂失
@Override
public void loseBank() {
if (mConsumer != null){
Log.e("hjcai","进行挂号等基础流程");
mConsumer.loseBank();
Log.e("hjcai","流程结束");
}
}
}
被代理类
// 消费者
public class Consumer implements IBank{
@Override
public void applyBank() {
Log.e("hjcai","申请新的银行卡");
}
@Override
public void loseBank() {
Log.e("hjcai","申请挂失");
}
// ......
}
动态代理demo
接口类
public interface IBank {
// 申请银行卡
void applyBank();
// 挂失
void loseBank();
}
代理类
实际上动态代理不需要创建代理类 但是需要创建一个继承自InvocationHandler的代理类方法被调用时的CallBack
/**
* {@code InvocationHandler} is the interface implemented by
* the <i>invocation handler</i> of a proxy instance.
*
* InvocationHandler是一个接口 该接口被invocation handler的代理实例实现
*
* <p>Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the {@code invoke}
* method of its invocation handler.
*
* 每个代理实例有一个相关联的调用handler
* 当代理实例的一个方法被调用时 该方法的调用会被编码并分发给他的invocation handler的invoke方法
*
* @author Peter Jones
* @see Proxy
* @since 1.3
*/
public class DynamicProxyCallBack implements InvocationHandler {
private final IBank mConsumer;
public DynamicProxyCallBack(IBank consumer) {
this.mConsumer = consumer;
}
/**
* Processes a method invocation on a proxy instance and returns
* the result. This method will be invoked on an invocation handler
* when a method is invoked on a proxy instance that it is
* associated with.
*
* @param proxy 调用对应方法的代理实例
*
* @param method 代理实例的对应的方法
*
* @param args 对应方法的参数
*
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.e("hjcai","做一些挂号等基础流程");
Object object = method.invoke(mConsumer, args);
Log.e("hjcai","流程结束");
return object;
}
}
被代理类
// 消费者
public class Consumer implements IBank{
@Override
public void applyBank() {
Log.e("hjcai","申请新的银行卡");
}
@Override
public void loseBank() {
Log.e("hjcai","申请挂失");
}
// ......
}
测试类(静态与动态代理demo共用)
public class MainActivity extends AppCompatActivity {
BusinessMan mBusinessMan;// 静态代理对象
IBank mConsumerProxy;// 动态代理对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 被代理对象
Consumer mConsumer = new Consumer();
// 静态代理对象
mBusinessMan = new BusinessMan(mConsumer);
// 动态代理对象
mConsumerProxy = (IBank) Proxy.newProxyInstance(
mConsumer.getClass().getClassLoader(),
mConsumer.getClass().getInterfaces(),
new DynamicProxyCallBack(mConsumer));
}
// 静态代理测试
public void staticApply(View view) {
// 调用的代理类的方法 但是核心内容调用的是真实类(消费者)的方法
mBusinessMan.applyBank();
}
// 静态代理测试
public void staticLose(View view) {
// 调用的代理类的方法 但是核心内容调用的是真实类(消费者)的方法
mBusinessMan.loseBank();
}
// 动态代理测试
public void dynamicLose(View view) {
mConsumerProxy.loseBank();
}
// 动态代理测试
public void dynamicApply(View view) {
mConsumerProxy.applyBank();
}
}
不管是静态代理还是动态代理 他们的结构都是 代理的接口+被代理类+代理类+测试类
可以看到动态代理与静态代理前两部分完全一致 少数不同的地方
1.代理对象的生成方式
2.代理方法调用时的处理方式不一样
Java动态代理生成方法newProxyInstance的源码浅析
这里选用的是API25的Proxy源码 因为到26的时候 源码已经发生了巨大的变化 其中有个proxyClassCache变量 完全不知道内部是如何操作的 只能看看API25的源码了
大致思路
调用Java的代理类生成方法生成一个代理类
代理类调用方法的时候 invoke方法被调用 并且知道调用的方法和参数
需要知道为什么 代理类调用方法的时候 invoke方法是如何调用的
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// 判空
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
// 获取代理类的Class 用于反射生成代理类
Class<?> cl = getProxyClass0(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// 根据class+参数得到对应的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
// 将handler作为参数传进创建Instance的方法 newInstance方法后继续跟进 发现最终调用的是native方法
// 但是我们可以猜测 该对象将handler作为内部变量 当调用代理对象的方法的时候 通过handler通知外部方法被调用
return newInstance(cons, h);
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
// 获取代理类的Class类型
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
// 判断接口数目合法性
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 声明返回的Class类型对象
Class<?> proxyClass = null;
/* collect interface names to use as key for proxy class cache */
// 所有接口的名称集合
String[] interfaceNames = new String[interfaces.length];
// 利用interfaceNames+interfaceSet进行接口名称的去重 已经接口合法性检测
// for detecting duplicates
Set<Class<?>> interfaceSet = new HashSet<>();
for (int i = 0; i < interfaces.length; i++) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
String interfaceName = interfaces[i].getName();
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) {
throw new IllegalArgumentException(
interfaces[i] + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.contains(interfaceClass)) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
/*
* Using string representations of the proxy interfaces as
* keys in the proxy class cache (instead of their Class
* objects) is sufficient because we require the proxy
* interfaces to be resolvable by name through the supplied
* class loader, and it has the advantage that using a string
* representation of a class makes for an implicit weak
* reference to the class.
*/
// 使用string(而不是类对象)在代理类的缓存中作为key代表代理接口已经足够
// 因为 我们需要代理接口可以根据提供的class loader按照名字来区别
// 并且使用string还有一个优势 即 使用string代表一个class作为与该类真正的Class关联弱引用的一个key
List<String> key = Arrays.asList(interfaceNames);
/*
* Find or create the proxy class cache for the class loader.
*/
// 做一个缓存
Map<List<String>, Object> cache;
synchronized (loaderToCache) {
cache = loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap<>();
loaderToCache.put(loader, cache);
}
/*
* This mapping will remain valid for the duration of this
* method, without further synchronization, because the mapping
* will only be removed if the class loader becomes unreachable.
*/
}
/*
* Look up the list of interfaces in the proxy class cache using
* the key. This lookup will result in one of three possible
* kinds of values:
* null, if there is currently no proxy class for the list of
* interfaces in the class loader,
* the pendingGenerationMarker object, if a proxy class for the
* list of interfaces is currently being generated,
* or a weak reference to a Class object, if a proxy class for
* the list of interfaces has already been generated.
*/
synchronized (cache) {
/*
* Note that we need not worry about reaping the cache for
* entries with cleared weak references because if a proxy class
* has been garbage collected, its class loader will have been
* garbage collected as well, so the entire cache will be reaped
* from the loaderToCache map.
*/
do {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class<?>) ((Reference) value).get();
}
// 存在缓存
if (proxyClass != null) {
// proxy class already generated: return it
return proxyClass;
} else if (value == pendingGenerationMarker) {
// proxy class being generated: wait for it
try {
cache.wait();
} catch (InterruptedException e) {
/*
* The class generation that we are waiting for should
* take a small, bounded time, so we can safely ignore
* thread interrupts here.
*/
}
continue;
} else {
/*
* No proxy class for this list of interfaces has been
* generated or is being generated, so we will go and
* generate it now. Mark it as pending generation.
*/
cache.put(key, pendingGenerationMarker);
break;
}
} while (true);
}
// 上面有些不明白 初次初始化的时候怎么终结上面的死循环???
try {
// 准备获取代理对象包名
String proxyPkg = null; // package to define proxy class in
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {// 跳过非public的接口
String name = interfaces[i].getName();
// 取得最后一个点
int n = name.lastIndexOf('.');
// 最后一个点之前的部分是包名
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// 没有非公开接口的代理接口的包名 使用空包名
// if no non-public proxy interfaces, use the default package.
proxyPkg = "";
}
{
// Android-changed: Generate the proxy directly instead of calling
// through to ProxyGenerator.
// 获取接口的所有方法
List<Method> methods = getMethods(interfaces);
// 排序
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
// 确认返回类型
validateReturnTypes(methods);
// 查看是否抛出异常
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
// 转换为数组
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
// 异常改变为二维数组
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
/*
* Choose a name for the proxy class to generate.
*/
final long num;
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
// 代理类的名称:
// 包名+前缀($Proxy)+当前实例在多线程中的index
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 调用native方法 得到代理对象的class
proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
} finally {
/*
* We must clean up the "pending generation" state of the proxy
* class cache entry somehow. If a proxy class was successfully
* generated, store it in the cache (with a weak reference);
* otherwise, remove the reserved entry. In all cases, notify
* all waiters on reserved entries in this cache.
*/
synchronized (cache) {
if (proxyClass != null) {
cache.put(key, new WeakReference<Class<?>>(proxyClass));
} else {
cache.remove(key);
}
cache.notifyAll();
}
}
// 返回代理对象的class 继续查看newProxyInstance方法
return proxyClass;
}
private final static String proxyClassNamePrefix = "$Proxy";
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
ClassLoader loader, Method[] methods,
Class<?>[][] exceptions);
private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
try {
return cons.newInstance(new Object[] {h} );
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString());
}
}
}
public T newInstance(Object... args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (serializationClass == null) {
// newInstance0 newInstanceFromSerialization都是native方法
return newInstance0(args);
} else {
return (T) newInstanceFromSerialization(serializationCtor, serializationClass);
}
}
private static native Object newInstanceFromSerialization(Class<?> ctorClass, Class<?> allocClass)
throws InstantiationException, IllegalArgumentException, InvocationTargetException;
private native T newInstance0(Object... args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException;
总结动态代理
1.解析interface所有方法
2.新建一个class,class的name: 包名+$Proxy+所处线程index,
3.通过native实例化代理proxy对象,proxy的里面包含InvocationHandler
4.每次调代理类方法会通知InvocationHandler里面的invoke方法 并告知调用了什么方法传递的什么参数等信息
第四步中很多信息其实隐藏在c++层 这里只是猜测
相比于静态代理,动态代理不需要我们自己创建代理类 并且我们可以在方法调用的前后做统一的处理,但是如果我们在各个方法前后需要进行不一样的处理 那么这个时候就更应该选择静态代理了吧?
最后想到一个可以用静态代理模拟动态代理的方法 不过相比于真正的动态代理的灵活性 还是有不少差距
@Override
public void applyBank() {
//申请银行卡
if (mConsumer != null) {
beforeOperation();
mConsumer.applyBank();
afterOperation();
}
}
private void beforeOperation(){
Log.e("hjcai", "beforeOperation");
}
private void afterOperation(){
Log.e("hjcai", "afterOperation");
}