zoukankan      html  css  js  c++  java
  • JdkDynamicAopProxy-笔记

    这个接口的继承体系图:

     一、AopProxy

    InvocationHandler就不说了,看看AopProxy的源码。

    /**
     * Delegate interface for a configured AOP proxy, allowing for the creation
     * of actual proxy objects.
     *
     * <p>Out-of-the-box implementations are available for JDK dynamic proxies
     * and for CGLIB proxies, as applied by {@link DefaultAopProxyFactory}.
     *
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @see DefaultAopProxyFactory
     */
    public interface AopProxy {
    
        /**创建一个代理对象。(为目标对象创建一个代理对象。)
         * Create a new proxy object.
         * <p>Uses the AopProxy's default class loader (if necessary for proxy creation):
         * usually, the thread context class loader.
         * @return the new proxy object (never {@code null})
         * @see Thread#getContextClassLoader()
         */
        Object getProxy();
    
        /**重载方法。上面的无参方法会调用这个重载方法。
         * Create a new proxy object.
         * <p>Uses the given class loader (if necessary for proxy creation).
         * {@code null} will simply be passed down and thus lead to the low-level
         * proxy facility's default, which is usually different from the default chosen
         * by the AopProxy implementation's {@link #getProxy()} method.
         * @param classLoader the class loader to create the proxy with
         * (or {@code null} for the low-level proxy facility's default)
         * @return the new proxy object (never {@code null})
         */
        Object getProxy(ClassLoader classLoader);
    
    }

     二、JdkDynamicAopProxy

    /**
     * JDK-based {@link AopProxy} implementation for the Spring AOP framework,
     * based on JDK {@link java.lang.reflect.Proxy dynamic proxies}.
     *
     * <p>Creates a dynamic proxy, implementing the interfaces exposed by
     * the AopProxy. Dynamic proxies <i>cannot</i> be used to proxy methods
     * defined in classes, rather than interfaces.
     *
     * <p>Objects of this type should be obtained through proxy factories,
     * configured by an {@link AdvisedSupport} class. This class is internal
     * to Spring's AOP framework and need not be used directly by client code.
     *
     * <p>Proxies created using this class will be thread-safe if the
     * underlying (target) class is thread-safe.
     *
     * <p>Proxies are serializable so long as all Advisors (including Advices
     * and Pointcuts) and the TargetSource are serializable.
     *
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @author Rob Harrop
     * @author Dave Syer
     * @see java.lang.reflect.Proxy
     * @see AdvisedSupport
     * @see ProxyFactory
     */
    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    
        /** use serialVersionUID from Spring 1.2 for interoperability */
        private static final long serialVersionUID = 5531744639992436476L;
    
    
        /*
         * NOTE: We could avoid the code duplication between this class and the CGLIB
         * proxies by refactoring "invoke" into a template method. However, this approach
         * adds at least 10% performance overhead versus a copy-paste solution, so we sacrifice
         * elegance for performance. (We have a good test suite to ensure that the different
         * proxies behave the same :-)
         * This way, we can also more easily take advantage of minor optimizations in each class.
         */
    
        /** We use a static Log to avoid serialization issues */
        private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
    
        /** Config used to configure this proxy */
        private final AdvisedSupport advised;
    
        /**
         * Is the {@link #equals} method defined on the proxied interfaces?
         */
        private boolean equalsDefined;
    
        /**
         * Is the {@link #hashCode} method defined on the proxied interfaces?
         */
        private boolean hashCodeDefined;
    
    
        /**
         * Construct a new JdkDynamicAopProxy for the given AOP configuration.
         * @param config the AOP configuration as AdvisedSupport object
         * @throws AopConfigException if the config is invalid. We try to throw an informative
         * exception in this case, rather than let a mysterious failure happen later.
         */
        public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
            Assert.notNull(config, "AdvisedSupport must not be null");
            if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("No advisors and no TargetSource specified");
            }
            this.advised = config;
        }
    
    
        @Override
        public Object getProxy() {
            return getProxy(ClassUtils.getDefaultClassLoader());
        }
    
        @Override
        public Object getProxy(ClassLoader classLoader) {
            if (logger.isDebugEnabled()) {
                logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
            }
         //代理接口。代理对象的接口,通常包括目标对象的实现的接口、Advised接口、SpringProxy接口 Class
    <?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);//返回代理对象。 } /** * Finds any {@link #equals} or {@link #hashCode} method that may be defined * on the supplied set of interfaces. * @param proxiedInterfaces the interfaces to introspect */ private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) { for (Class<?> proxiedInterface : proxiedInterfaces) { Method[] methods = proxiedInterface.getDeclaredMethods(); for (Method method : methods) { if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } } /** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try {
    //是否重写了euquals方法,并且当前调用的方法就是的equals方法.
    if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. //是否重写了hashCode方法并且当前调用的是hashCode方法。
    return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. //尽量晚点获取目标对象。
    target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method.获取目标方法对应的拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) {//如果拦截器链为空,那么直接调用目标对象。 // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
    //拦截器链为空的话就不需要创建MethodInvocation对象(连接点)了,直接调用目标对象。 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation...
    //拦截器链不为空,创建一个调用
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain.
    //开始调用拦截器链和目标方法.
    retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } } /** * Equality means interfaces, advisors and TargetSource are equal. * <p>The compared object may be a JdkDynamicAopProxy instance itself * or a dynamic proxy wrapping a JdkDynamicAopProxy instance. */ @Override public boolean equals(Object other) { if (other == this) { return true; } if (other == null) { return false; } JdkDynamicAopProxy otherProxy; if (other instanceof JdkDynamicAopProxy) { otherProxy = (JdkDynamicAopProxy) other; } else if (Proxy.isProxyClass(other.getClass())) { InvocationHandler ih = Proxy.getInvocationHandler(other); if (!(ih instanceof JdkDynamicAopProxy)) { return false; } otherProxy = (JdkDynamicAopProxy) ih; } else { // Not a valid comparison... return false; } // If we get here, otherProxy is the other AopProxy. return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised); } /** * Proxy uses the hash code of the TargetSource. */ @Override public int hashCode() { return JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); } }
  • 相关阅读:
    hdu 5224 Tom and paper 水题
    2015 UESTC 搜索专题N题 韩爷的梦 hash
    2015 UESTC 搜索专题M题 Palindromic String 马拉车算法
    2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp
    2015 UESTC 搜索专题J题 全都是秋实大哥 kmp
    2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
    2015 UESTC 搜索专题E题 吴队长征婚 爆搜
    2015 UESTC 搜索专题D题 基爷的中位数 二分
    2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
    2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
  • 原文地址:https://www.cnblogs.com/GooPolaris/p/8232814.html
Copyright © 2011-2022 走看看