`

spring AOP源码分析之获取代理对象

阅读更多
下面我们来看看Spring的AOP的一些相关代码是怎么得到Proxy的,让我们我们先看看AOP和Spring AOP的一些基本概念:
Advice:
    通知,制定在连接点做什么,在Sping中,他主要描述Spring围绕方法调用注入的额外的行为,Spring提供的通知类型有:
    before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,这些都是Spring AOP定义的接口类,具体的动作实现需要用户程序来完成。
Pointcut:
    切点,其决定一个advice应该应用于哪个连接点,也就是需要插入额外处理的地方的集合,例如,被某个advice作为目标的一组方法。Spring pointcut通常意味着标示方法,可以选择一组方法调用作为pointcut,Spring提供了具体的切点来给用户使用,比如正则表达式切点 JdkRegexpMethodPointcut通过正则表达式对方法名进行匹配,其通过使用 AbstractJdkRegexpMethodPointcut中的对MethodMatcher接口的实现来完成pointcut功能:
Java代码 
public final boolean matches(Method method, Class targetClass) {  
    //这里通过放射得到方法的全名  
    String patt = method.getDeclaringClass().getName() + "." + method.getName();  
    for (int i = 0; i < this.patterns.length; i++) {  
        // 这里是判断是否和方法名是否匹配的代码  
        boolean matched = matches(patt, i);  
        if (matched) {  
            for (int j = 0; j < this.excludedPatterns.length; j++) {  
                boolean excluded = matchesExclusion(patt, j);  
                if(excluded) {  
                    return false;  
                }  
            }  
            return true;  
        }  
    }  
    return false;  


    public final boolean matches(Method method, Class targetClass) {
        //这里通过放射得到方法的全名
        String patt = method.getDeclaringClass().getName() + "." + method.getName();
        for (int i = 0; i < this.patterns.length; i++) {
            // 这里是判断是否和方法名是否匹配的代码
            boolean matched = matches(patt, i);
            if (matched) {
                for (int j = 0; j < this.excludedPatterns.length; j++) {
                    boolean excluded = matchesExclusion(patt, j);
                    if(excluded) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

在JDKRegexpMethodPointcut中通过JDK中的正则表达式匹配来完成pointcut的最终确定:
Java代码 
protected boolean matches(String pattern, int patternIndex) {  
    Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);  
    return matcher.matches();  


    protected boolean matches(String pattern, int patternIndex) {
        Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
        return matcher.matches();
    }

Advisor:
当我们完成额外的动作设计(advice)和额外动作插入点的设计(pointcut)以后,我们需要一个对象把他们结合起来,这就是通知器 - advisor,定义应该在哪里应用哪个通知。Advisor的实现有:DefaultPointcutAdvisor他有两个属性advice和 pointcut来让我们配置advice和pointcut。
 
在ProxyFactoryBean 中,它的AOP实现需要依赖JDK和GCLIB提供的Proxy特性,从FcatoryBean中获取对象,是用getObject()方法作为入口完成,让我们进入ProxyFactoryBean中获取对象,是用getObject()方法作为入口完成的;让我们进入ProxyFactoryBean的实现中去,这个我们一点也不陌生的getObject()方法,是FactoryBean需要实现的接口。对ProxyFactoryBean来说,把需要对target目标对象增加的增强处理 ,都通过getObject的实现代码

//获取对象
public Object getObject()
        throws BeansException
    {
        //初始化通知其链
        initializeAdvisorChain();
        if(isSingleton())
              //返回单例对象
            return getSingletonInstance();
        if(targetName == null)
            logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
        return newPrototypeInstance();
    }

//对Advisor配置链的初始化

private synchronized void initializeAdvisorChain()
        throws AopConfigException, BeansException
    {
        if(advisorChainInitialized)
            return;
        if(!ObjectUtils.isEmpty(interceptorNames))
        {
            if(beanFactory == null)
                throw new IllegalStateException((new StringBuilder("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names ")).append(Arrays.asList(interceptorNames)).toString());
            if(interceptorNames[interceptorNames.length - 1].endsWith("*") && targetName == null && targetSource == EMPTY_TARGET_SOURCE)
                throw new AopConfigException("Target required after globals");
            String as[];
            int j = (as = interceptorNames).length;
            for(int i = 0; i < j; i++)
            {
                String name = as[i];
                if(logger.isTraceEnabled())
                    logger.trace((new StringBuilder("Configuring advisor or advice '")).append(name).append("'").toString());
                if(name.endsWith("*"))
                {
                    if(!(beanFactory instanceof ListableBeanFactory))
                        throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");
                    addGlobalAdvisor((ListableBeanFactory)beanFactory, name.substring(0, name.length() - "*".length()));
                } else
                {
                    Object advice;
                    if(singleton || beanFactory.isSingleton(name))
                        advice = beanFactory.getBean(name);
                    else
                        advice = new PrototypePlaceholderAdvisor(name);
                    addAdvisorOnChainCreation(advice, name);
                }
            }

        }
        advisorChainInitialized = true;
    }


如果是生成singleton对象则在getSingleton中完成
    private synchronized Object getSingletonInstance()
    {
        if(singletonInstance == null)
        {
            targetSource = freshTargetSource();
            if(autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass())
            {
                Class targetClass = getTargetClass();
                if(targetClass == null)
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                //设置代理接口
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, proxyClassLoader));
            }
            super.setFrozen(freezeProxy);
            singletonInstance = getProxy(createAopProxy());
        }
        return singletonInstance;
    }
这里出现了AopProxy类型的对象是spring把AOP代理对象的实现与框架的其他部分有效的分离开,AopProxy是一个接口,它有两个子类实现
一个Cglib2AopProxy和JdkDynamicAopProxy,spring 是通过CGLIB和JDK来生成需要的Proxy代理对象。

在ProxyCreatorSupport 中的  createAopProxy()方法
protected final synchronized AopProxy createAopProxy()
    {
        if(!active)
            activate();
        
        return getAopProxyFactory().createAopProxy(this);
    }

在 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.");
            else
                //采用cglib方式产生代理对象
                return CglibProxyFactory.createCglibProxy(config);
        } else
        {
            //采用jdk动态代理产生代理对象
            return new JdkDynamicAopProxy(config);
        }
    }


protected Object getProxy(AopProxy aopProxy)
    {
        return aopProxy.getProxy(proxyClassLoader);
    }

如果是CGlib方式,则产生代理对象,则在Cglib2AopProxy中的getProxy方法其源码如下:
public Object getProxy(ClassLoader classLoader)
    {
        try
        {
            Class rootClass = 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();
                Class aclass[];
                int j = (aclass = additionalInterfaces).length;
                for(int i = 0; i < j; i++)
                {
                    Class additionalInterface = aclass[i];
                    advised.addInterface(additionalInterface);
                }
            }
            validateClassIfNecessary(proxySuperClass);
            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(java/lang/reflect/UndeclaredThrowableException));
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(advised));
            enhancer.setInterceptDuringConstruction(false);
            Callback callbacks[] = getCallbacks(rootClass);
            enhancer.setCallbacks(callbacks);
            enhancer.setCallbackFilter(new ProxyCallbackFilter(advised.getConfigurationOnlyCopy(), fixedInterceptorMap, fixedInterceptorOffset));
            Class types[] = new Class[callbacks.length];
            for(int x = 0; x < types.length; x++)
                types[x] = callbacks[x].getClass();

            enhancer.setCallbackTypes(types);
            Object proxy;
            if(constructorArgs != null)
                proxy = enhancer.create(constructorArgTypes, constructorArgs);
            else
                proxy = enhancer.create();
            return proxy;
        }    
        catch(Exception ex)
        {
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }


我们在来看下JdkDynamicAopProxy 实现了InvokeHandle和Aopproxy接口jdk的代理方式。
public Object getProxy(ClassLoader classLoader)
    {
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder("Creating JDK dynamic proxy: target source is ")).append(advised.getTargetSource()).toString());
        Class proxiedInterfaces[] = AopProxyUtils.completeProxiedInterfaces(advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        //这是jdk的代理方式,将执行invoke方法
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

这样用Proxy包装target之后,通过ProxyFactoryBean得到对其方法的调用就被Proxy拦截了, ProxyFactoryBean的getObject()方法得到的实际上是一个Proxy了,我们的target对象已经被封装了。对 ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对象的代理对象。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics