Spring AOP 之动态代理源码分析

本文参考网址: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 }
原文地址:https://www.cnblogs.com/dousil/p/12859005.html