Spring源码分析-初识ProxyFactoryBean(五)

 2019-11-23 11:08  阅读(785)
文章分类:Spring Cloud

这一节我们进入Spring的AOP功能的源码解析。

一:首先我们来看一下ProxyFactoryBean的继承层次

Object

—-ProxyConfig

—-AdvisedSupport

—-ProxyCreatorSupport

—-ProxyFactoryBean

在这里,ProxyConfig是一个数据类,这个数据基类为像ProxyFactoryBean这样的子类提供了配置属性。

AdvisedSupport封装了AOP中对通知和通知器的相关操作。

ProxyCreatorSupport是子类创建AOP代理对象的一个辅助类

二:ProxyFactoryBean的getObject

/**
         * Return a proxy. Invoked when clients obtain beans from this factory bean.
         * Create an instance of the AOP proxy to be returned by this factory.
         * The instance will be cached for a singleton, and create on each call to
         * <code>getObject()</code> for a proxy.
         * @return a fresh AOP proxy reflecting the current state of this factory
         */
        public Object getObject() throws BeansException {
            initializeAdvisorChain();
            if (isSingleton()) {
                return getSingletonInstance();
            }
            else {
                if (this.targetName == null) {
                    logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                            "Enable prototype proxies by setting the 'targetName' property.");
                }
                return newPrototypeInstance();
            }
        }

为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中实现的。

我们来看看initializeAdvisorChain的源码实现:

/**
         * Create the advisor (interceptor) chain. Aadvisors that are sourced
         * from a BeanFactory will be refreshed each time a new prototype instance
         * is added. Interceptors added programmatically through the factory API
         * are unaffected by such changes.
         */
        private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
            if (this.advisorChainInitialized) {
                return;
            }

            if (!ObjectUtils.isEmpty(this.interceptorNames)) {
                if (this.beanFactory == null) {
                    throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                            "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
                }

                // Globals can't be last unless we specified a targetSource using the property...
                if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                        this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                    throw new AopConfigException("Target required after globals");
                }

                // Materialize interceptor chain from bean names.
                for (int i = 0; i < this.interceptorNames.length; i++) {
                    String name = this.interceptorNames[i];
                    if (logger.isTraceEnabled()) {
                        logger.trace("Configuring advisor or advice '" + name + "'");
                    }

                    if (name.endsWith(GLOBAL_SUFFIX)) {
                        if (!(this.beanFactory instanceof ListableBeanFactory)) {
                            throw new AopConfigException(
                                    "Can only use global advisors or interceptors with a ListableBeanFactory");
                        }
                        addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                                name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                    }

                    else {
                        // If we get here, we need to add a named interceptor.
                        // We must check if it's a singleton or prototype.
                        Object advice = null;
                        if (this.singleton || this.beanFactory.isSingleton(this.interceptorNames[i])) {
                            // Add the real Advisor/Advice to the chain.
                            advice = this.beanFactory.getBean(this.interceptorNames[i]);
                        }
                        else {
                            // It's a prototype Advice or Advisor: replace with a prototype.
                            // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                            advice = new PrototypePlaceholderAdvisor(this.interceptorNames[i]);
                        }
                        addAdvisorOnChainCreation(advice, this.interceptorNames[i]);
                    }
                }
            }

            this.advisorChainInitialized = true;
        }

在这个方法中,最核心的操作是addGlobalAdvisor和addAdvisorOnChainCreation,我们来看一下addAdvisorOnChainCreation的源码

/**
         * Invoked when advice chain is created.
         * <p>Add the given advice, advisor or object to the interceptor list.
         * Because of these three possibilities, we can't type the signature
         * more strongly.
         * @param next advice, advisor or target object
         * @param name bean name from which we obtained this object in our owning
         * bean factory
         */
        private void addAdvisorOnChainCreation(Object next, String name) {
            // We need to convert to an Advisor if necessary so that our source reference
            // matches what we find from superclass interceptors.
            Advisor advisor = namedBeanToAdvisor(next);
            if (logger.isTraceEnabled()) {
                logger.trace("Adding advisor with name '" + name + "'");
            }           
            addAdvisor((Advisor) advisor);
        }

在这里addAdvisor实际上是在父类AdvisorSupport里实现的,是把实例化的Advisor加入到AdvisorSupport的实例变量advisors(LinkedList)中。

现在我们回到ProxyFactoryBean的getObject中,来看一下getSingletonInstance的源码实现。

/**
         * Return the singleton instance of this class's proxy object,
         * lazily creating it if it hasn't been created already.
         * @return the shared singleton proxy
         */
        private synchronized Object getSingletonInstance() {
            if (this.singletonInstance == null) {
                this.targetSource = freshTargetSource();
                if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                    // Rely on AOP infrastructure to tell us what interfaces to proxy.
                    Class targetClass = getTargetClass();
                    if (targetClass == null) {
                        throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                    }
                    setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
                }
                // Initialize the shared singleton instance.
                super.setFrozen(this.freezeProxy);
                this.singletonInstance = getProxy(createAopProxy());
            }
            return this.singletonInstance;
        }

我们可以看到属性singletonInstance用来缓存这个单件对象,具体的获取是通过getProxy(createAopProxy())方法来完成的。

/**
         * Return the proxy object to expose.
         * <p>The default implementation uses a <code>getProxy</code> call with
         * the factory's bean class loader. Can be overridden to specify a
         * custom class loader.
         * @param aopProxy the prepared AopProxy instance to get the proxy from
         * @return the proxy object to expose
         * @see AopProxy#getProxy(ClassLoader)
         */
        protected Object getProxy(AopProxy aopProxy) {
            return aopProxy.getProxy(this.proxyClassLoader);
        }

我们首先来看一下createAopProxy方法的源码,这个方法是在父类ProxyCreatorSupport中实现的。

/**
         * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
         * create an AOP proxy with <code>this</code> as an argument.
         */
        protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            return getAopProxyFactory().createAopProxy(this);
        }

getAopProxyFactory()方法返回的DefaultAopProxyFactory,我们来看看DefaultAopProxyFactory是如何createAopProxy的。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                Class targetClass = config.getTargetClass();
                if (targetClass == null) {
                    throw new AopConfigException("TargetSource cannot determine target class: " +
                            "Either an interface or a target is required for proxy creation.");
                }
                if (targetClass.isInterface()) {
                    return new JdkDynamicAopProxy(config);
                }
                if (!cglibAvailable) {
                    throw new AopConfigException(
                            "Cannot proxy target class because CGLIB2 is not available. " +
                            "Add CGLIB to the class path or specify proxy interfaces.");
                }
                return CglibProxyFactory.createCglibProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }

根据源码我们可以看出DefaultAopProxyFactory根据不同的需要生成JdkDynamicAopProxy或者Cglib2AopProxy.现在我们来看看JdkDynamicAopProxy是怎样完成AopProxy代理对象生成工作的。

JdkDynamicAopProxy生成Proxy代理对象源码:

public Object getProxy(ClassLoader classLoader) {
            if (logger.isDebugEnabled()) {
                logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
            }
            Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }

重点关注Proxy.newProxyInstance这个代理方法,通过this我们知道JdkDynamicAopProxy implements InvocationHandler,对于invoke方法的源码留待下一节讲解。

我们现来看一下Cglib2AopProxy是如何getProxy的。

public Object getProxy(ClassLoader classLoader) {
            if (logger.isDebugEnabled()) {
                logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());
            }

            try {
                Class rootClass = this.advised.getTargetClass();
                Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

                Class proxySuperClass = rootClass;
                if (AopUtils.isCglibProxyClass(rootClass)) {
                    proxySuperClass = rootClass.getSuperclass();
                    Class[] additionalInterfaces = rootClass.getInterfaces();
                    for (int i = 0; i < additionalInterfaces.length; i++) {
                        Class additionalInterface = additionalInterfaces[i];
                        this.advised.addInterface(additionalInterface);
                    }
                }

                // Validate the class, writing log messages as necessary.
                validateClassIfNecessary(proxySuperClass);

                // Configure CGLIB Enhancer...
                Enhancer enhancer = createEnhancer();
                if (classLoader != null) {
                    enhancer.setClassLoader(classLoader);
                    if (classLoader instanceof SmartClassLoader &&
                            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                        enhancer.setUseCache(false);
                    }
                }
                enhancer.setSuperclass(proxySuperClass);
                enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
                enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
                enhancer.setInterceptDuringConstruction(false);

                Callback[] callbacks = getCallbacks(rootClass);
                enhancer.setCallbacks(callbacks);
                enhancer.setCallbackFilter(new ProxyCallbackFilter(
                        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

                Class[] types = new Class[callbacks.length];
                for (int x = 0; x < types.length; x++) {
                    types[x] = callbacks[x].getClass();
                }
                enhancer.setCallbackTypes(types);

                // Generate the proxy class and create a proxy instance.
                Object proxy;
                if (this.constructorArgs != null) {
                    proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
                }
                else {
                    proxy = enhancer.create();
                }

                return proxy;
            }
            catch (CodeGenerationException ex) {
                throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                        this.advised.getTargetClass() + "]: " +
                        "Common causes of this problem include using a final class or a non-visible class",
                        ex);
            }
            catch (IllegalArgumentException ex) {
                throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                        this.advised.getTargetClass() + "]: " +
                        "Common causes of this problem include using a final class or a non-visible class",
                        ex);
            }
            catch (Exception ex) {
                // TargetSource.getTarget() failed
                throw new AopConfigException("Unexpected AOP exception", ex);
            }
        }

我们进入getCallbacks方法来看看是如何生成callback的

private Callback[] getCallbacks(Class rootClass) throws Exception {
            // Parameters used for optimisation choices...
            boolean exposeProxy = this.advised.isExposeProxy();
            boolean isFrozen = this.advised.isFrozen();
            boolean isStatic = this.advised.getTargetSource().isStatic();

            // Choose an "aop" interceptor (used for AOP calls).
            Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

            // Choose a "straight to target" interceptor. (used for calls that are
            // unadvised but can return this). May be required to expose the proxy.
            Callback targetInterceptor = null;

            if (exposeProxy) {
                targetInterceptor = isStatic ?
                        (Callback) new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                        (Callback) new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
            }
            else {
                targetInterceptor = isStatic ?
                        (Callback) new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                        (Callback) new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
            }

            // Choose a "direct to target" dispatcher (used for
            // unadvised calls to static targets that cannot return this).
            Callback targetDispatcher = isStatic ?
                    (Callback) new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

            Callback[] mainCallbacks = new Callback[]{
                aopInterceptor, // for normal advice
                targetInterceptor, // invoke target without considering advice, if optimized
                new SerializableNoOp(), // no override for methods mapped to this
                targetDispatcher, this.advisedDispatcher,
                new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised)
            };

            Callback[] callbacks;

            // If the target is a static one and the advice chain is frozen,
            // then we can make some optimisations by sending the AOP calls
            // direct to the target using the fixed chain for that method.
            if (isStatic && isFrozen) {
                Method[] methods = rootClass.getMethods();
                Callback[] fixedCallbacks = new Callback[methods.length];
                this.fixedInterceptorMap = new HashMap(methods.length);

                // TODO: small memory optimisation here (can skip creation for
                // methods with no advice)
                for (int x = 0; x < methods.length; x++) {
                    List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
                    fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                            chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                    this.fixedInterceptorMap.put(methods[x].toString(), new Integer(x));
                }

                // Now copy both the callbacks from mainCallbacks
                // and fixedCallbacks into the callbacks array.
                callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];

                for (int x = 0; x < mainCallbacks.length; x++) {
                    callbacks[x] = mainCallbacks[x];
                }

                for (int x = 0; x < fixedCallbacks.length; x++) {
                    callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
                }

                this.fixedInterceptorOffset = mainCallbacks.length;
            }
            else {
                callbacks = mainCallbacks;
            }
            return callbacks;
        }

最核心的方法同样留到下一节再介绍。

// Choose an "aop" interceptor (used for AOP calls).
            Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

来源:http://ddrv.cn/a/88268

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring源码分析-初识ProxyFactoryBean(五)

相关推荐