首先有三个主要类 接口类,接口实现类 和处理器实现类(处理器实现类生成代理类)
处理器实现类代码:
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) { //target是一个接口实现类,它实现了接口,所以可以传进来
this.target = target;
}
public Object proxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), //分别是你要代理的接口类的加载器(因为是面向接口代理的),那个类里的接口以及当前类对象(即代理类对象) 我们创建的ProxyHandler类会通过构造方法自动注入到生成代理类中。
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aspect before ... ");
Object result = method.invoke(this.target, args);
System.out.println("aspect after ... ");
return result;
}
}
处理器实现类代码:
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) { //target是一个接口实现类,它实现了接口,所以可以传进来
this.target = target;
}
public Object proxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), //分别是你要代理的接口类的加载器(因为是面向接口代理的),那个类里的接口以及当前类对象(即代理类对象) 我们创建的ProxyHandler类会通过构造方法自动注入到生成代理类中。
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aspect before ... ");
Object result = method.invoke(this.target, args);
System.out.println("aspect after ... ");
return result;
}
}
main函数:
public class Main {
public static void main(String[] args) {
ProxyHandler proxy = new ProxyHandler(new HelloImpl());
IHello hello = (IHello) proxy.proxyInstance(); //生成接口代理类
hello.sayHello();
}
}
public class Main {
public static void main(String[] args) {
ProxyHandler proxy = new ProxyHandler(new HelloImpl());
IHello hello = (IHello) proxy.proxyInstance(); //生成接口代理类
hello.sayHello();
}
}
public interface IHello {
public void sayHello();
}
public class HelloImpl implements IHello {
public void sayHello() {
System.out.println("Hello World...");
}
}
过程解析:newProxyInstance() 方法 是获取代理类的 Class 对象的方法 然后通过反射(通过构造器)生成代理类的实例,并返回。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) //上面的this是指ProxyHandler实例对象,实现了InvocationHandler ,所以可以当参数传进来
throws IllegalArgumentException {
Class<?> cl = getProxyClass0(loader, intfs);
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
cons.setAccessible(true);
return cons.newInstance(new Object[]{h}); //把ProxyHandler类通过构造方法自动注入到生成代理类中。
} catch (Exception e) {
......
}
}
getProxyClass0() 方法
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
1.检查需要代理的类的接口数量是否超过65535个,接口个数用2个byte存储,最大支持65535个。
2.到proxyClassCache中找到对应的代理类并返回。因为代理类的Class对象存进proxyClassCache。 一个弱引用缓存区
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
2.到proxyClassCache中找到对应的代理类并返回。因为代理类的Class对象存进proxyClassCache。 一个弱引用缓存区
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
proxyClassCache.get() 方法
1.首先通过 classLoader 获取该classLoader下所有的代理类缓存map。 因为proxyClassCache就是一个WeakCache<ClassLoader, Class<?>[], Class<?>> 类加载器,interfaces[]标识代理类Class<?>[]即代理类需要实现的接口数组,代理类Class<?>
https://www.cnblogs.com/James-Gong/p/8126129.html
2.从该代理类缓存map中根据代理类所有实现的所有接口进行查找代理类。因为key是classLoader和interfaces[]标识代理类组成,即ClassLoader, Class<?>[],value为代理类Class<?> 用的是二级缓存。如果都没有找到对应的代理类,则使用ProxyClassFactory.apply() 方法生成代理类
1.首先通过 classLoader 获取该classLoader下所有的代理类缓存map。 因为proxyClassCache就是一个WeakCache<ClassLoader, Class<?>[], Class<?>> 类加载器,interfaces[]标识代理类Class<?>[]即代理类需要实现的接口数组,代理类Class<?>
https://www.cnblogs.com/James-Gong/p/8126129.html
2.从该代理类缓存map中根据代理类所有实现的所有接口进行查找代理类。因为key是classLoader和interfaces[]标识代理类组成,即ClassLoader, Class<?>[],value为代理类Class<?> 用的是二级缓存。如果都没有找到对应的代理类,则使用ProxyClassFactory.apply() 方法生成代理类
// 通过类加载器classLoader生成以及一级缓存key
Object cacheKey = CacheKey.valueOf(key, refQueue);
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
// 获取二级缓存,不存在则新建
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// 获取二级缓存,不存在则新建
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
// 生成二级缓存key
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
// 通过key获取二级缓存value,即缓存的代理类。不存在则新建代理类并加入缓存。
// subKey from valuesMap
// 生成二级缓存key
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
// 通过key获取二级缓存value,即缓存的代理类。不存在则新建代理类并加入缓存。
ProxyClassFactory.apply()方法
1.生成代理类的包名和类名
2.通过ProxyGenerator.generateProxyClass() 方法动态生成代理类字节码。
3.通过classloader 动态加载 字节码,并生成动态代理类的Class实例,并返回
1.生成代理类的包名和类名
2.通过ProxyGenerator.generateProxyClass() 方法动态生成代理类字节码。
3.通过classloader 动态加载 字节码,并生成动态代理类的Class实例,并返回
ProxyGenerator.generateProxyClass()方法
1.添加默认的代理方法 hashCode、equals、toString 三个代理方法以及代理的接口类的实现类的实现方法
2.循环迭代所有的接口,把接口中所有的方法都生成代理方法。
1.添加默认的代理方法 hashCode、equals、toString 三个代理方法以及代理的接口类的实现类的实现方法
2.循环迭代所有的接口,把接口中所有的方法都生成代理方法。
生成的class文件 中会有hashCode、equals、toString及代理的接口类的实现类的实现方法
该代理类继承了Proxy,并把我们创建的ProxyHandler 类通过构造方法自动注入到 代理类中。
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object proxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); ///因此这里的最后一个参数是当前类对象
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aspect before ... ");
Object result = method.invoke(this.target, args);
System.out.println("aspect after ... ");
return result;
}
}
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object proxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); ///因此这里的最后一个参数是当前类对象
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aspect before ... ");
Object result = method.invoke(this.target, args);
System.out.println("aspect after ... ");
return result;
}
}
当我们调用代理类的sayHello方法时,sayHello方法就会调用我们实现的ProxyHandler类中的invoke() 方法,ProxyHandler.invoke() 方法调用我们真正的目标类的sayHello方法。因此可以在ProxyHandler.invoke() 方法扩展
public class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
public Object proxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), //分别是你要代理的接口类的加载器(因为是面向接口代理的),那个类里的接口以及当前类对象(即代理类对象) 我们创建的ProxyHandler类会通过构造方法自动注入到生成代理类中。
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)//这个method即main函数的 hello.sayHello();的sayHello()方法
throws Throwable {
System.out.println("aspect before ... ");
Object result = method.invoke(this.target, args); //如果sayHello()方法有参数,在这传进去。
System.out.println("aspect after ... ");
return result;
}
}
main函数:
public class Main {
public static void main(String[] args) {
ProxyHandler proxy = new ProxyHandler(new HelloImpl());
IHello hello = (IHello) proxy.proxyInstance();
hello.sayHello();
}
}
总的步骤:Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);生成代理类,他里面调用了getProxyClass0(ClassLoader loader, Class<?>... interfaces)方法,判断要实现代理的类的接口数量是否超了以及通过 classLoader 获取该classLoader下所有的代理类缓存map即proxyClassCache ,再从proxyClassCache 中根据类加载器以及代理类需要实现的接口数组去找相应的代理类,也就是proxyClassCache 这个为二级缓存里key是类加载器以及代理类需要实现的接口数组,value是对应的代理类。如果没有则会调用ProxyClassFactory.apply()生成代理类,ProxyClassFactory.apply()又会调用ProxyGenerator.generateProxyClass()生成类字节码文件,主要是添加默认的 hashCode、equals、toString 三个代理方法以及要实现代理的接口类的实现类的方法。最后通过classloader 动态加载 字节码,并生成动态代理类的Class实例,并返回。
因此main函数里首先通过ProxyHandler proxy = new ProxyHandler(new HelloImpl());生成处理器实现类,然后调用处理器实现类的proxyInstance()生成代理类并强制转换为接口类,因为这个代理类里已经实现了该类里接口的所有方法以及hashCode、equals、toString三个方法。调用hello.sayHello();时就会调用ProxyHandler的invoke方法(因为代理类的所有方法都是通过invoke()调用的),ProxyHandler.invoke() 方法调用我们真正的目标类的sayHello方法。也因此可以ProxyHandler的invoke方法里进行扩展