1 Java动态代理
1.1 代理模式
1.2 静态代理
package com.cl.dynamicproxy;
import com.cl.utils.TimeUtils;
/**
* @Author chenlan
* @Date 2020/10/11 14:13
* @Description 静态代理的实现:
*
* 需求:创建代理对象,代理学生上交学费
*
* 01 目标对象与代理对象应该具备相同的功能(公共接口、抽象主体)
* class Student implements IPerson{}
* class StudentProxy implements IPerson{}
*
* 02 代理对象应该持有目标对象的引用,可以随意的访问目标对象
* (mybatis dao的实现类、动态代理处理事务、动态代理处理日志、动态代理处理连接,动态代理计算程序的执行时间)
* private IPerson student;
*
* 03 代理对象相对于目标对象来说可以扩展功能
*
* 04 目标对象不直接依赖客户,依赖代理对象即可,降低了耦合度
*
* 实际开发中,dao接口有很多的实现类,使用静态代理要分别去写他们的代理对象,会使代理类暴增
* 所以我们希望在程序运行时动态代理
*/
public class DynamicProxyDemo {
public static void main(String[] args) {
// 创建真实对象
IPerson student = new Student("alex");
student.payMoney();
System.out.println(student.add(1, 100));
System.out.println("-------------------");
// 创建代理对象
StudentProxy studentProxy = new StudentProxy(student);
studentProxy.payMoney();
System.out.println(studentProxy.add(1, 100));
}
}
/**
* 定义抽象主体[公共接口]
*/
interface IPerson {
void payMoney();
long add(int m, int n);
}
/**
* 定义目标对象,即真实对象
*/
class Student implements IPerson {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
@Override
public void payMoney() {
System.out.println(this.name + "上交学费");
}
@Override
public long add(int m, int n) {
int sum = 0;
for (int i = m; i <= n; i++) {
sum += i;
}
return sum;
}
}
class StudentProxy implements IPerson {
private IPerson student;
public StudentProxy(IPerson student) {
if (student instanceof Student) {
this.student = student;
}
}
@Override
public void payMoney() {
this.prePay();
student.payMoney();
this.postPay();
}
public void prePay() {
System.out.println("StudentProxy.prePay");
}
public void postPay() {
System.out.println("StudentProxy.postPay");
}
@Override
public long add(int m, int n) {
TimeUtils.start();
long addVar = student.add(m, n);
TimeUtils.finish("add");
return addVar;
}
}
1.3 动态代理
1.4 动态代理原理分析
package com.cl.dynamicproxy;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author chenlan
* @Date 2020/10/11 14:54
* @Description 动态代理的实现
*
* 三个角色
* 抽象主体(最核心)
* 目标对象
* 代理对象
*
* jdk提供生成代理的方法
*/
public class DynamicProxyDemo2 {
public static void main(String[] args) {
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", Student.class.getInterfaces());
try (FileOutputStream fos = new FileOutputStream("e:\\test\\StudentProxy.class")) {
fos.write(bytes);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Student代理对象源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.cl.dynamicproxy.IPerson;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements IPerson {
private static Method m1; // equals方法
private static Method m2; // toString方法
private static Method m3; // add方法
private static Method m4; // payMoney方法
private static Method m0; // hashCode方法
// 反射获取目标对象的同名方法
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.cl.dynamicproxy.IPerson").getMethod("add", Integer.TYPE, Integer.TYPE);
m4 = Class.forName("com.cl.dynamicproxy.IPerson").getMethod("payMoney");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
// 当外界调用该构造方法的时候,需要传入一个InvocationHandler接口
// 反射创建该对象的时候会传入该对象的实现类
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final long add(int var1, int var2) throws {
try {
/**
* h: 外界传递过来的InvocationHandler
* h.invoke: 本质是外界传递过来的InvocationHandler.invoke
* @param this: 动态代理对象
* @param m3: add方法
* @param new Object[]{var1, var2}: 参数
*/
return (Long)super.h.invoke(this, m3, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
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 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 payMoney() throws {
try {
super.h.invoke(this, m4, (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);
}
}
}
Proxy类部分源码:
public class Proxy implements java.io.Serializable {
protected InvocationHandler h;
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
// 创建代理类对应的class对象,有了class对象就能够通过反射创建代理对象
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
{
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
return getProxyClass0(loader, intfs);
}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
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);
/*
* Invoke its constructor with the designated invocation handler.
*/
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);
}
}
}
interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
实现动态代理:
package com.cl.dynamicproxy;
import com.cl.utils.TimeUtils;
import java.lang.reflect.*;
/**
* @Author chenlan
* @Date 2020/10/11 14:54
* @Description 动态代理的实现
*
*/
public class DynamicProxyDemo4 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Student student = new Student("coco");
// 创建动态代理类对应的class对象
/**
* @params ClassLoader loader 类加载器:这里使用加载Strudent类的加载器来加载代理类(将代理类装载到内存)
* @params Class<?>... interfaces :用来创建代理类
*/
final Class<?> proxyClass = Proxy.getProxyClass(Student.class.getClassLoader(), Student.class.getInterfaces());
final Constructor<?> conn = proxyClass.getDeclaredConstructor(InvocationHandler.class);
final IPerson s = (IPerson) conn.newInstance(new MyInvocationHandler<Student>(student));
s.payMoney();
System.out.println(s.add(1, 100));
}
}
// 代理过程
class MyInvocationHandler<Student> implements InvocationHandler{
// 持有目标对象的引用
private Student student;
public MyInvocationHandler(Student student) {
this.student = student;
}
/**
*
* @param proxy 代理对象
* @param method 实际上调用的方法
* @param args 参数
* @return 最终返回给代理对象的调用者
* @throws Throwable
*
* 代理对象调用方法 -> 触发invoke方法 -> 传递参数(实际上调用目标对象的同名方法) -> 返回值给代理对象 -> 代理对象返回给代理对象的调用者
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName();
Object result = null;
switch (methodName) {
case "payMoney":
System.out.println("prePay");
result = method.invoke(student, args);
System.out.println("postPay");
break;
case "add":
TimeUtils.start();
result = method.invoke(student, args);
TimeUtils.finish("add");
break;
}
return result;
}
}
实现动态代理:
package com.cl.dynamicproxy;
import com.cl.utils.TimeUtils;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author chenlan
* @Date 2020/10/11 14:54
* @Description 动态代理的实现
*
*/
public class DynamicProxyDemo3 {
public static void main(String[] args) {
Student student = new Student("coco");
final IPerson proxy = (IPerson) Proxy.newProxyInstance(Student.class.getClassLoader(), Student.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName();
Object result = null;
switch (methodName) {
case "payMoney":
System.out.println("prePay");
result = method.invoke(student, args);
System.out.println("postPay");
break;
case "add":
TimeUtils.start();
result = method.invoke(student, args);
TimeUtils.finish("add");
break;
}
return result;
}
});
proxy.payMoney();
System.out.println(proxy.add(1, 100));
}
}