1、角色
抽象接口、真实类处理业务逻辑、代理类
03、01JAVA代理模式角色.png2、静态代理:在编译期间确定代理类、被代理类,由程序员创建生成代理类
代理模式: 代理类持有具体类的实例对象,代为执行具体类实例的方法。代理模式实际是在访问具体对象时引入了一定程度的间接性,而这种间接性可以附加额外的用途,一般是想在方法执行前后添加逻辑判断。如:取钱业务,需要先判断账户是否有钱等。
场景:AOP面向切面编程:在一个切点之前执行一些操作,在一个切点之后执行一些操作,其中这些切点就是一个个的方法,而这些方法就是所在类被代理,在代理过程中切入一些其他的操作。
缺点:造成接口增多,一个代理会实现多个接口,不变维护修改;
如下例子:班级学生需要向老师上交班费,需要先将班费交给班长,再由班长代理班级同学上交班费;
public interface OnPersonSerivce {
void classFreeAction();//上交班费行为
}
/**
* 学生,接口的具体实现类
*/
public class StudentServiceImpl implements OnPersonSerivce {
String name; //名字
int classFree; //班费
public StudentServiceImpl(String name, int classFree) {
this.name = name;
this.classFree = classFree;
}
/**
* 交班费
*/
@Override
public void classFreeAction() {
System.out.println(name + " 上交班费 " + classFree + "元");
}
}
/**
* 代理类,班长
*/
public class StudentServiceProxy implements OnPersonSerivce {
OnPersonSerivce mOnPersonSerivce; //具体的实现类
public StudentServiceProxy(OnPersonSerivce onUserSerivce) {
// if (onUserSerivce.getClass() == StudentServiceImpl.class) {
// //只代理 StudentServiceImpl学生对象
// }
mOnPersonSerivce = onUserSerivce;
}
@Override
public void classFreeAction() {
System.out.println("-- 代理类中classFreeAction start --");
mOnPersonSerivce.classFreeAction();
System.out.println("-- 代理类中classFreeAction end(班长收到班费) --");
}
}
//调用静态代理
public class MyMainClass {
public static void main(String[] args) {
//被代理类 (班级同学)
StudentServiceImpl student = new StudentServiceImpl("张三",30);
//代理类 (班长)
StudentServiceProxy proxy = new StudentServiceProxy(student);
//代理类执行 (班长上交班费)
proxy.classFreeAction();
}
}
输出打印:
-- 代理类中classFreeAction start --
张三 上交班费 30元
-- 代理类中classFreeAction end(班长收到班费) --
3、动态代理:在程序运行时创建的代理方式,代理类是在运行时动态生成的
优点:可以方便对代理类的方法统一进行管理,而不用修改代理类中的方法;
涉及的类:java.lang.reflect.Proxy、InvocationHandler接口类(监听回调);通过这个Proxy类和InvocationHandler接口可以生成JDK的动态代理类和动态代理对象。
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler InvocationHandler = new MyInvocationHandler<OnPersonSerivce>(stu);
//创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
OnPersonSerivce stuProxy= (OnPersonSerivce) Proxy.newProxyInstance(OnPersonSerivce.class.getClassLoader(), new Class<?>[]{OnPersonSerivce.class}, InvocationHandler);
stuProxy.classFreeAction();
其中可以通过以下代码,获取打印内存中的类文件;
try {
String name = StudentServiceImpl.class.getName() + "$Proxy0";
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{StudentServiceImpl.class});
FileOutputStream fos = new FileOutputStream("lib/" + name + ".class");
fos.write(bytes);
fos.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("write file error");
}
动态生成的代理类文件如下:其中 Method m3 是 classFreeAction方法,自己写的方法。
public final class StudentServiceImpl$Proxy0 extends Proxy implements StudentServiceImpl {
private static Method m1;
private static Method m8;
private static Method m2;
private static Method m3;
private static Method m5;
private static Method m4;
private static Method m7;
private static Method m9;
private static Method m0;
private static Method m6;
public StudentServiceImpl$Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void notify() throws {
try {
super.h.invoke(this, m8, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void classFreeAction() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void wait(long var1) throws InterruptedException {
try {
super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | InterruptedException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final void wait(long var1, int var3) throws InterruptedException {
try {
super.h.invoke(this, m4, new Object[]{var1, var3});
} catch (RuntimeException | InterruptedException | Error var5) {
throw var5;
} catch (Throwable var6) {
throw new UndeclaredThrowableException(var6);
}
}
public final Class getClass() throws {
try {
return (Class)super.h.invoke(this, m7, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notifyAll() throws {
try {
super.h.invoke(this, m9, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void wait() throws InterruptedException {
try {
super.h.invoke(this, m6, (Object[])null);
} catch (RuntimeException | InterruptedException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m8 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("notify");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("classFreeAction");//自己定义的方法
m5 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("wait", Long.TYPE);
m4 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("wait", Long.TYPE, Integer.TYPE);
m7 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("getClass");
m9 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("notifyAll");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m6 = Class.forName("com.izheer.lib.proxys.StudentServiceImpl").getMethod("wait");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
4、Proxy.java newProxyInstance的源码分析
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();//拷贝代理接口class对象集合
// Android-removed: SecurityManager calls
/*
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
*/
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs); //获取到Class对象
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// Android-removed: SecurityManager / permission checks.
/*
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
*/
final Constructor<?> cons = cl.getConstructor(constructorParams); //通过反射获取class的对象的构造器
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
// BEGIN Android-removed: Excluded AccessController.doPrivileged call.
/*
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
*/
cons.setAccessible(true);
// END Android-removed: Excluded AccessController.doPrivileged call.
}
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);
}
}
从newProxyInstance方法看出生成动态代理类的步骤
//拷贝代理接口class对象集合
1、final Class<?>[] intfs = interfaces.clone();
2、 Class<?> cl = getProxyClass0(loader, intfs);//获取到Class对象
//通过反射获取class的对象的构造方法
3、final Constructor<?> cons = cl.getConstructor(constructorParams);
//对构造方法进行实例化,实际返回的是 第2点中的Class对象
//(类加载器在内存中生成的Class对象,见底部类加载流程图中的 Class对象节点)
4、return cons.newInstance(new Object[]{h});
总结步骤
创建动态代理类对象的步骤,如下:对应newProxyInstance的源码
1、使用Proxy类的getProxyClass静态方法生成一个动态代理类
Class<?> proxyClass = Proxy.getProxyClass(OnPersonSerivce.class.getClassLoader(), new Class[]{OnPersonSerivce.class});
2、利用反射,获取代理类Class(proxyClass)对象的构造器Constructor(带有一个InvocationHandler参数的构造器)
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
3、通过构造器Constructor 创建一个动态实例
StudentServiceImpl o = (StudentServiceImpl) constructor.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
return null;
}
});
通过实现类似Retrofit的基本使用demo,加深对动态代理、注解、发射的理解与使用
Retrofit接口的使用流程:
A、当api接口被调用时,Retrofit会被动态代理拦截然后调用代理中的InvocationHandler对象,在invoke方法中传入参数;
B、然后利用反射获取接口方法的注解信息,子路径地址,请求方式类型;请求参数key值;
C、最后获取到的注解信息配合args参数,创建一个ServiceMethod对象,在ServiceMethod中组合成一个request,最后由Okhttp发送Request;
具体demo:ProxyRetrofit上传github
其中,click包中实现onClick的注入,类似ButterKnife 的 OnClick点击事件注入
JAVA类的完整生命周期
java源文件 —编译—> 字节码(.class文件)—类加载器—> Class对象(jvm中可识别的对象)—实例—>实例对象 ——>卸载
java类加载流程
java类加载流程.png
网友评论