本文参考网址:https://www.jianshu.com/p/9bcac608c714 https://www.cnblogs.com/yaowen/p/10117893.html
Class<?> string01 = person.getClass().getInterfaces()[0];
使用说明,在动态代理中使用到了该方法,该方法的作用是获得对象的所有
1. SecurityManager应用场景
当运行未知的java程序的时候,该程序可能有恶意代码(删除粗系统文件,重启系统),位了防止运行恶意代码对系统产生影响,需要对运行的代码权限控制。这个时候就需要启动java安全管理器。
2. Reflection.getCallerClass()此方法的调用者必须要有权限,需要什么样的权限了,
由bootstrap class loader 加载类可以调用
由extension calss loader 加载类可以调用
3. 我们都知道用户路径的类加载是由application calss loader进行加载的,换句话说,用户自定义的一些类无法调用该方法。
4. Reflection.getCallerCalss()方法调用所在的方法必须要加注解@CallerSensitive进行注解。
这个方法的使用: 可以得到调用者的类。
1 返回自己的类
2. 返回调用者的类
3. 4.5 层层上传
5.具体的实例
public interface HelloService { void sayHello(); }
public class HelloServiceProxy implements InvocationHandler{ private Object target; public Object bind(Object target, Class[] interfaces) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result; System.out.println("###########这里是动态代理##########"); //反射方法前调用 System.out.println("调用前"); //反射执行方法 相当于调用target.sayHelllo; result = method.invoke(target,args); //反射方法后调用. System.out.println("调用后"); return result; } }
public class ProxyTest { public static void main(String[] args) { HelloServiceProxy proxy = new HelloServiceProxy(); HelloService service = new HelloServiceImpl(); HelloService serviceProxy = (HelloService)proxy.bind(service, new Class[] {HelloService.class}); serviceProxy.sayHello(); } }
源码分析:Proxy 类静态方法NewProxyInstance
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //如果h为空,抛出空指针异常。 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); } //获取参数类型是InvocationHandler.class的代理类构造器 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; } }); } //传入InvocationHandler实例去构造一个代理类的实例,所有代理类都继承自Proxy,而Proxy构造方法需要InvocationHandler实例作为参数 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); } }
从newProxyInstance 方法看出,产生代理类核心代码在getProxyClas0()
private static Class<?> getProxyClass0(ClassLoader loader, 2 Class<?>... interfaces) { 3 if (interfaces.length > 65535) { 4 throw new IllegalArgumentException("interface limit exceeded"); 5 } 6 7 // If the proxy class defined by the given loader implementing 8 // the given interfaces exists, this will simply return the cached copy; 9 // otherwise, it will create the proxy class via the ProxyClassFactory 10 //如果由实现给定接口的代理类存在,这将简单地返回缓存的副本;否则,将通过ProxyClassFactory创建代理类 11 return proxyClassCache.get(loader, interfaces); 12 }
getProxyClas0通过类加载器和接口集合取缓存里边获取,如果能找到直接返回,否则就会调用ProxyClassFactory这个工厂去生成一个代理类,下面我们看下Proxy的静态内部类。
private static final class ProxyClassFactory 2 implements BiFunction<ClassLoader, Class<?>[], Class<?>> 3 { 4 // prefix for all proxy class names 代理类名称前缀 5 private static final String proxyClassNamePrefix = "$Proxy"; 6 7 // next number to use for generation of unique proxy class names, 用原子类来生成代理类的序号, 保证序号唯一 8 private static final AtomicLong nextUniqueNumber = new AtomicLong(); 9
//loader ,以及它代替的接口类 10 @Override 11 public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { 12 13 Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); 14 for (Class<?> intf : interfaces) { 15 /* 16 * Verify that the class loader resolves the name of this 17 * interface to the same Class object. 18 */ 19 Class<?> interfaceClass = null; 20 try { 21 interfaceClass = Class.forName(intf.getName(), false, loader); 22 } catch (ClassNotFoundException e) { 23 } 24 //intf是否可以由指定的类加载进行加载 25 if (interfaceClass != intf) { 26 throw new IllegalArgumentException( 27 intf + " is not visible from class loader"); 28 } 29 /* 30 * Verify that the Class object actually represents an 31 * interface. 32 * intf是否是一个接口 33 */ 34 if (!interfaceClass.isInterface()) { 35 throw new IllegalArgumentException( 36 interfaceClass.getName() + " is not an interface"); 37 } 38 /* 39 * Verify that this interface is not a duplicate. 40 * intf在数组中是否有重复 41 */ 42 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { 43 throw new IllegalArgumentException( 44 "repeated interface: " + interfaceClass.getName()); 45 } 46 } 47 // package to define proxy class in 生成代理类的包名 48 String proxyPkg = null; 49 // 代理类的访问标志, 默认是public final 50 int accessFlags = Modifier.PUBLIC | Modifier.FINAL; 51 52 /* 53 * Record the package of a non-public proxy interface so that the 54 * proxy class will be defined in the same package. Verify that 55 * all non-public proxy interfaces are in the same package. 56 * 验证所有非公共代理接口都在同一个包中 57 */ 58 for (Class<?> intf : interfaces) { 59 //获取接口的访问标志 60 int flags = intf.getModifiers(); 61 //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同 62 if (!Modifier.isPublic(flags)) { 63 //生成的代理类的访问标志设置改为final 64 accessFlags = Modifier.FINAL; 65 String name = intf.getName(); 66 int n = name.lastIndexOf('.'); 67 String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); 68 if (proxyPkg == null) { 69 proxyPkg = pkg; 70 } else if (!pkg.equals(proxyPkg)) { 71 //代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错 72 throw new IllegalArgumentException( 73 "non-public interfaces from different packages"); 74 } 75 } 76 } 77 78 if (proxyPkg == null) { 79 // if no non-public proxy interfaces, use com.sun.proxy package 如果没有非公共代理接口,那生成的代理类都放到默认的包下:com.sun.proxy 80 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; 81 } 82 83 /* 84 * Choose a name for the proxy class to generate. 85 * 生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0 86 */ 87 long num = nextUniqueNumber.getAndIncrement(); 88 String proxyName = proxyPkg + proxyClassNamePrefix + num; 89 90 /* 91 * Generate the specified proxy class. 92 * 这里是核心, 用ProxyGenerator来生成字节码, 该类放在sun.misc包下 93 */ 94 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( 95 proxyName, interfaces, accessFlags); 96 //根据二进制文件生成相应的Class实例 97 try { 98 return defineClass0(loader, proxyName, 99 proxyClassFile, 0, proxyClassFile.length); 100 } catch (ClassFormatError e) { 101 /* 102 * A ClassFormatError here means that (barring bugs in the 103 * proxy class generation code) there was some other 104 * invalid aspect of the arguments supplied to the proxy 105 * class creation (such as virtual machine limitations 106 * exceeded). 107 */ 108 throw new IllegalArgumentException(e.toString()); 109 } 110 } 111 }