1.例子
在了解Java动态代理技术之前,先了解一下什么是代理模式,其实代理模式在生活中很常见,比如房东与中介其实就是一个代理的过程,房东有自己的房子,在代理模式中扮演角色是被代理对象,中介扮演角色是代理对象,此时有租客想租房子,由于中介已经代理了房东的房子,所以租客(客户端)可以直接通过中介(代理对象)询问自己需要的房子类型(忽略租客直接找房东),中介由于代理了房东的房子(被代理对象),当然中介可以代理多个房东的房子,以应对不同的租客(客户端).这 个过程其实就是代理模式
2.结论
代理模式的角色:代理对象、被代理对象、公共抽象类(租客要找的房子类型在中介中要有)
代理对象可以代理一个或者多个对象(其实都是代理一个,多个对象的概念从接口维度出发,一个对象实现多个接口)
代理模式可以起到一个隔离的作用
代理模式可以统一为被代理对象做处理
2.代理模式的几种实现方式
1.静态代理
静态代理实现起来相对简单,首先从从上面我们知道代理对象的几个角色,一个公共抽象接口、一个代理对象、一个被代理对象,所以只需要在代理对象里记录被代理对象的引用即可
public class StudentProxy implements Person {
private Person person;
public StudentProxy(Person person) {
this.person = person;
}
@Override
public void queryScore(String courseName) {
person.queryScore(courseName);
}
}
public class Student implements Person{
private String userName;
public Student(String userName) {
this.userName = userName;
}
@Override
public void queryScore(String courseName) {
System.out.println(this.userName+"查"+courseName+"的成绩");
}
}
public interface Person {
void queryScore(String courseName);
}
总结: 1.静态代理,实现简单,但如果存在多个类要被代理,则需要为每个被代理类建立一个代理类,并且每个方法都要重写,然后在方法中调用被代理对象对于的方法。2.代理对象是我们人为编写的。)
2.动态代理0) @[TOC](1.JDK动态代理 实现原理以及技术 首先jdk动态代理的实现是基于Java反射技术以及字节码生成技术来实现的,它是先通过反射获取到被代理类的方法然后生成一个包含了被代理类所有方法的Proxy子类来实现代理。 jdk动态代理的代理对象是动态生成的,并非手动编写 实现代码理
实现原理以及技术
首先jdk动态代理的实现是基于Java反射技术以及字节码生成技术来实现的,它是先通过反射获取到被代理类的方法然后生成一个包含了被代理类所有方法的Proxy子类来实现代理。
jdk动态代理的代理对象是动态生成的,并非手动编写
实现代码
public interface Good {
void produce();
}
public interface Person {
void queryScore(String courseName);
}
public class Student implements Person{
private String userName;
public Student(String userName) {
this.userName = userName;
}
@Override
public void queryScore(String courseName) {
System.out.println(this.userName+"查"+courseName+"的成绩");
}
}
public class PersonInvocation implements InvocationHandler {
private T target;
private Object target2;
public PersonInvocation(T target) {
this.target = target;
}
public PersonInvocation(T target, Object target2) {
this.target = target;
this.target2 = target2;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理前置处理....");
System.out.println(proxy.getClass().getName());
Object result = method.invoke(target, args);
System.out.println("代理后置处理.....");
return result;
}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
Person stu1 = new Student("zs");
PersonInvocation personInvocation = new PersonInvocation<>(stu1);
//获取根据类加载器以及接口集生成的代理类
Class> proxyClass = Proxy.getProxyClass(Student.class.getClassLoader(),Person.class,Good.class);
//根据代理类和构造器参数获取类构造器
Constructor> constructor = proxyClass.getConstructor(InvocationHandler.class);
//执行被代理后的被代理对象
Person o = (Person) constructor.newInstance(personInvocation);
Good good = (Good) constructor.newInstance(personInvocation);
good.produce();
//上面代码等同与下面这一条语句
Good proxyInstance = (Good) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class,Good.class}, personInvocation);
byte[] proxyClassArr = ProxyGenerator.generateProxyClass(proxyInstance.getClass()
.getSimpleName(), proxyInstance.getClass().getInterfaces());
//将字节码文件保存到D盘,文件名为$Proxy0.class
FileOutputStream outputStream = new FileOutputStream(new File(
"proxyInstance.class"));
outputStream.write(proxyClassArr);
outputStream.flush();
outputStream.close();
proxyInstance.produce();
}
}
//代理类
public final class $Proxy0 extends Proxy implements Person, Good {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
private static Method m4;
//省略.....
public final void gaiveMoney() 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 produce() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | 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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("learning.proxy.Person").getMethod("gaiveMoney");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m4 = Class.forName("learning.proxy.Good").getMethod("produce");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
总结: 从代码反编译后的代理类实现可以看到,如果从接口维度出发确实可以代理多个对象,另外可以看出jdk动态代理是在运行时动态生成字节码技术以及反射技术来实现的.
源码分析
Proxy类中
@CallerSensitive
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);
}
@CallerSensitive
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);
}
Class> cl = getProxyClass0(loader, intfs);
//前面这一部分和getProxyClass方法是一致的
//下面这部分主要是根据invocationHandler作为参数获取代理类的实例对象
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() {
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);
}
}
//从缓存中获取代理类,如果不存在则生成
private static Class> getProxyClass0(ClassLoader loader,
Class>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
//缓存获取
return proxyClassCache.get(loader, interfaces);
}
//private final ConcurrentMap
总结:
1.jdk动态代理其实就是通过Java反射把被代理类的接口方法获取到然后生成一个新的代理类,通过类加载器把生成的代理类字节码动态调入jvm中从而实现动态代理。
2.jdk动态代理只能代理基于接口的被代理对象,非接口是不支持的)
2.cglib代理(支持非接口被代理对象)
待续…



