您的位置:首页 > 编程语言 > Java开发

spring源码分析,重新认识spring 二(aop实现详细分析)

2017-09-21 11:14 489 查看
为什么使用jdk 动态代理来实现,而且实现的是接口的代理。

jdk实现接口的代理 主要用的是Proxy.newProxyInstance 方法

该方法返回代理对象,该代理对象实现传入的接口,并且继承了Proxy 类

代理类开头概如下:

public final class $Proxy0 extends Proxy implements Person

证明部分代码如下:

Class clazz = target.getClass();//target 是被代理对象

        

System.out.println(Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this) instanceof Proxy);  //此处输出 为 true

这只是个证明,然后导入源码包,跟入Proxy.newProxyInstance 方法查看

代码如吓

  @CallerSensitive

    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<?> cl = getProxyClass0(loader, intfs);

        /*

         * Invoke its constructor with the designated invocation handler.

         */

        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});

        } 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);

        }

    }

重点在于

 Class<?> cl = getProxyClass0(loader, intfs);

这里生成代理类的 Class,所以继续跟入该方法,如下

  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

        return proxyClassCache.get(loader, interfaces);

    }

发现是从 proxyClassCache 中取值的,继续跟入,代码如下

 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

        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

        Supplier<V> supplier = valuesMap.get(subKey);

        Factory factory = null;

        while (true) {

            if (supplier != null) {

                // supplier might be a Factory or a CacheValue<V> instance

                V value = supplier.get();

                if (value != null) {

                    return value;

                }

            }

            // else no supplier in cache

            // or a supplier that returned null (could be a cleared CacheValue

            // or a Factory that wasn't successful in installing the CacheValue)

            // lazily construct a Factory

            if (factory == null) {

                factory = new Factory(key, parameter, subKey, valuesMap);

            }

            if (supplier == null) {

                supplier = valuesMap.putIfAbsent(subKey, factory);

                if (supplier == null) {

                    // successfully installed Factory

                    supplier = factory;

                }

                // else retry with winning supplier

            } else {

                if (valuesMap.replace(subKey, supplier, factory)) {

                    // successfully replaced

                    // cleared CacheEntry / unsuccessful Factory

                    // with our Factory

                    supplier = factory;

                } else {

                    // retry with current supplier

                    supplier = valuesMap.get(subKey);

                }

            }

        }

    }

重点代码在于

 Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

注意其中的 subKeyFactory.apply(key, parameter) 方法,跟入,这里是个接口,选择ProxyClassFactory 实现类,该 实现类在Proxy (反射包的。package java.lang.reflect;)类中。

方法如下

 @Override

        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);

            for (Class<?> intf : interfaces) {

                /*

                 * Verify that the class loader resolves the name of this

                 * interface to the same Class object.

                 */

                Class<?> interfaceClass = null;

                try {

                    interfaceClass = Class.forName(intf.getName(), false, loader);

                } catch (ClassNotFoundException e) {

                }

                if (interfaceClass != intf) {

                    throw new IllegalArgumentException(

                        intf + " is not visible from class loader");

                }

                /*

                 * Verify that the Class object actually represents an

                 * interface.

                 */

                if (!interfaceClass.isInterface()) {

                    throw new IllegalArgumentException(

                        interfaceClass.getName() + " is not an interface");

                }

                /*

                 * Verify that this interface is not a duplicate.

                 */

                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {

                    throw new IllegalArgumentException(

                        "repeated interface: " + interfaceClass.getName());

                }

            }

            String proxyPkg = null;     // package to define proxy class in

            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*

             * Record the package of a non-public proxy interface so that the

             * proxy class will be defined in the same package.  Verify that

             * all non-public proxy interfaces are in the same package.

             */

            for (Class<?> intf : interfaces) {

                int flags = intf.getModifiers();

                if (!Modifier.isPublic(flags)) {

                    accessFlags = Modifier.FINAL;

                    String name = intf.getName();

                    int n = name.lastIndexOf('.');

                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));

                    if (proxyPkg == null) {

                        proxyPkg = pkg;

                    } else if (!pkg.equals(proxyPkg)) {

                        throw new IllegalArgumentException(

                            "non-public interfaces from different packages");

                    }

                }

            }

            if (proxyPkg == null) {

                // if no non-public proxy interfaces, use com.sun.proxy package

                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";

            }

            /*

             * Choose a name for the proxy class to generate.

             */

            long num = nextUniqueNumber.getAndIncrement();

            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*

             * Generate the specified proxy class.

             */

            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

                proxyName, interfaces, accessFlags);

            try {

                return defineClass0(loader, proxyName,

                                    proxyClassFile, 0, proxyClassFile.length);

            } catch (ClassFormatError e) {

                /*

                 * A ClassFormatError here means that (barring bugs in the

                 * proxy class generation code) there was some other

                 * invalid aspect of the arguments supplied to the proxy

                 * class creation (such as virtual machine limitations

                 * exceeded).

                 */

                throw new IllegalArgumentException(e.toString());

            }

        }

    }

这一步重要的是

   byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

                proxyName, interfaces, accessFlags);

根据传入的接口 生成代理类,生成好的如下(前面有说过)

public final class $Proxy0extends Proxy

  implements Person

上面那个方法 自己可以尝试调用下,这个方法调用的时候,需要引入 jdk 下面的 rt.jar,并且输出

byte[] bytes =ProxyGenerator.generateProxyClass("$Proxy0", new Class[] {Person.class});

        

        FileOutputStream fos = null;

        try {

            fos = new FileOutputStream(new File("D:/test/$Proxy0class"));

        

            fos.write(bytes);

            

            fos.flush();

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }finally{

            try {

                fos.close();

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

生成一个 class 文件 ,然后用反编译工具,jd-gui 去编译下,就可以看到 代理类的源码。这就是 aop 的java 源码实现过程。再跟下去就是 native方法了。

代码地址:http://download.csdn.net/download/bvcxz10328/9988571
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: