我是靠谱客的博主 虚拟绿草,最近开发中收集的这篇文章主要介绍SpringAop之JDK动态代理源码解析保姆级SpringAop之JDK动态代理源码解析,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
SpringAop之JDK动态代理源码解析
摘要
Aop代理模式看过Spring源码同学都知道很多用了代理模式,主要对其目标类方法调用前后做增强拦截,不改变目标方法情况下实现插拔。只需要定义一组代理类实现接口,通过反射方式调用。
演示
声明目标类接口、方法
//接口
public interface UserService {
int save(String name);
void update(String name);
}
//实现类
public class UserServiceImpl implements UserService{
@Override
public int save(String name) {
System.out.println(name+"save success");
return 1;
}
@Override
public void update(String name) {
System.out.println(name+"update success");
}
}
定义代理类 (关键)
//代理类 实现InvocationHandler接口 重写invoke方法
public class UserServiceProxy implements InvocationHandler {
//目标类
private Object target;
public UserServiceProxy(Object target) {
this.target = target;
}
//invoke 负责调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前操作....");
Object result = method.invoke(target, args);
System.out.println("执行后操作....");
return result;
}
}
启动调用
public class TestJdkProxy {
public static void main(String[] args) throws IOException {
//newProxyInstance 创建代理类
UserService proxy= (UserService)Proxy.newProxyInstance(UserService.class.getClassLoader(),
new Class[]{UserService.class},
new UserServiceProxy(new UserServiceImpl()));
//委托代理类调用目标方法 代码会进入invoke方法
proxy.save("nijo");
proxy.update("huhu");
}
}
执行前操作....
nijosave success
执行后操作....
执行前操作....
huhuupdate success
执行后操作....
源码扣核心
1. 跟newProxyInstance() 方法 3个参数
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代理类。关键
Class<?> cl = getProxyClass0(loader, intfs);
2.跟 getProxyClass0()方法
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
//上面译文 如果之前加载过会从缓存获取直接返回,否则使用ProxyClassFactory生成
return proxyClassCache.get(loader, interfaces);
}
3. 继续跟ProxyClassFactory类
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
//生成类名
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
//生成数字下标 类名+下标
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
/**省略.....
中间做了一些校验,校验是否接口、接口是否重复
**/
//生成代理类class文件
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
}
4. generateProxyClass()具体如何生成 (关键)
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
//开始具体生成class
final byte[] var4 = var3.generateClassFile();
5. 跟generateClassFile()方法 (关键)
private byte[] generateClassFile() {
//生成hashcode方法、equals方法、toString方法
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
//获取目标类所有方法
int var3;
Class var4;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;
//生成目标类所有方法进行代理,按照演示这里会有save()update()方法生成
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
this.addProxyMethod(var8, var4);
}
}
Iterator var11 = this.proxyMethods.values().iterator();
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}
Iterator var15;
try {
//添加构造方法 设置参数代理类接口
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
代理类讲述
generateClassFile()为主要生成代理类class字节码,单独生成class看看张什么样
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
"com.sun.proxy.$Proxy0", new Class[]{UserService.class});
FileOutputStream outputStream=new FileOutputStream("~/$Proxy1.class");
outputStream.write(proxyClassFile);
outputStream.flush();
outputStream.close();
//继承Proxy 实现目前类UserService
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m0;
//构造方法 参数代理类实现InvocationHandler接口
public $Proxy0(InvocationHandler var1) throws {
//将代理类设置到父类Proxy
super(var1);
}
//euqals方法
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);
}
}
//目标类UserService # Save方法
public final int save(String var1) throws {
try {
//通过父类Proxy到代理类重写invoke方法调用 代码就会走到演示中UserServiceProxy # invoke方法
return (Integer)super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
//Object # toString
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);
}
}
//目标类UserService # update方法
public final void update(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
//Object # hachCode方法
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);
}
}
//加载class时候初始化资源
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com.example.beanaop.jdkProxy.UserService").getMethod("save", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.example.beanaop.jdkProxy.UserService").getMethod("update", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
补充
源码扣核心第2步有讲到get()如果之前未加载过,执行ProxyClassFactory类生成,它是怎么调用ProxyClassFactory.apply()的呢?
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
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;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
//以上缓存未命中,就使用ProxyClassFactory.apply生成,这样就过度到第3步了
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
总结
- 源码核心方法generateClassFile 生成代理类$Proxy0。
- $Proxy0代理类 继承Proxy类,实现目标类接口UserService。
- 代理类包含 目标类接口UserService所有方法进行代理,有自身构造函数,实列化传递参数代理类实现InvocationHandler接口 ,并设置Proxy父类。
- 标类接口UserService所有方法进行代理 通过调用Prxoy父类InvocationHandler 进行路由到代理类UserServiceProxy#invoke方法调用。
最后
以上就是虚拟绿草为你收集整理的SpringAop之JDK动态代理源码解析保姆级SpringAop之JDK动态代理源码解析的全部内容,希望文章能够帮你解决SpringAop之JDK动态代理源码解析保姆级SpringAop之JDK动态代理源码解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复