理解动态代理底层
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
根据我的理解:
步骤
-
Objects.requireNonNull(h);
- 判断代理实例的调用处理程序对象不为空 也就是你目前实现的这个接口不为空
-
final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager();
final Class<?>[] intfs = interfaces.clone();
这个是获得你这个接口的克隆对象final SecurityManager sm = System.getSecInvocationHandlerurityManager();
这个是获得安全管理器,这里面是分配安全权限的地方。- 这个安全管理器的应用场景是:当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。
- 权限分为以下类别:文件、套接字、网络、安全性、运行时、属性、AWT、反射和可序列化。
-
if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs); }
-
这里是判断安全管理器不为空,然后执行代理访问的方法,第一个是获得调用反射这个类的对象,第二个参数就是你自己写的实现了InvocationHandler的类的对象,第三个参数就是你代理的接口对象
-
这个方法的实现是
-
private static void checkProxyAccess(Class<?> caller,ClassLoader loader,Class<?>... interfaces){SecurityManager sm = System.getSecurityManager();if (sm != null) {ClassLoader ccl = caller.getClassLoader();if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);}ReflectUtil.checkProxyPackageAccess(ccl, interfaces);}}
-
SecurityManager sm = System.getSecurityManager();
- 这个同样是拿到系统安全管理器
-
if (sm != null) {ClassLoader ccl = caller.getClassLoader();if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);}ReflectUtil.checkProxyPackageAccess(ccl, interfaces);}
- 这个先判断管理器是否为空,不为空时
- 1、获取Reflection调用反射这个类的对象的类加载器。
- 2、判断调用我实现了InvocationHandler必须是系统类加载器的也就是AppClassLoader以及调用反射类的对象不能是系统类加载器(AppClassLoader)
- 3、然后调用检查权限,检查的是运行时权限
- 4、·
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
检查代理包的访问public static final String PROXY_PACKAGE = "com.sun.proxy";
-
-
-
Class<?> cl = getProxyClass0(loader, intfs);
-
这个获得代理类
-
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 ProxyClassFactoryreturn proxyClassCache.get(loader, interfaces);}
- 上面是判断class字节码文件的大小的如果超出了就报错
- return中的get方方法就是搞缓存的 太多了不想看了
-
-
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});
- 1、获得安全管理器
- 2、检查新代理的权限,就是检查包名和类加载器,
- 3、判断代理类的修饰符是否为public,不是的话就继续走
- 4、就是设置权限,可访问
- 5、返回一个新实例