`

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而言,其生产出来的对象是封装了目标对象的代理对象。
分享到:
评论

相关推荐

    在spring中获取代理对象代理的目标对象工具类

    本文将深入探讨如何在Spring中通过自定义工具类获取代理对象所代理的目标对象。 ### 核心概念:AOP与Spring Proxy 在理解如何获取目标对象之前,我们需要先了解Spring AOP的实现机制。Spring AOP主要通过动态代理...

    spring-aop-ProxyFactoryBean 源码分析

    `ProxyFactoryBean`是Spring AOP实现中的一个重要类,它用于创建代理对象,使我们能够实现动态代理以进行方法拦截。下面将深入分析`ProxyFactoryBean`的源码,探讨其工作原理和使用方式。 `ProxyFactoryBean`继承自...

    springAOP核心组件分析.pdf

    AnnotationAwareAspectJAutoProxyCreator类是Spring AOP用来创建代理对象的核心组件之一。它通过扫描类上标注了特定AOP注解的类(如@Aspect)并根据这些信息来创建代理对象。当容器中的bean需要创建时,...

    Spring AOP的底层实现技术

    当我们通过Spring容器获取一个bean时,实际上是获取了它的代理对象。代理对象在调用目标方法前后,会根据通知类型执行相应的逻辑。比如,如果定义了一个前置通知,那么在调用目标方法之前,前置通知会被执行。 6. ...

    Spring AOP

    Spring AOP的源码分析主要涉及以下几个部分: - **ProxyFactoryBean**:它是Spring AOP代理的工厂类,负责创建代理对象。 - **Advised**:接口,代表可以配置通知的对象,如代理对象。 - **AopProxy**:接口,定义了...

    spring aop的一点东东

    Spring AOP是基于代理的,它提供了声明式的方式来实现AOP。 1. **切面(Aspect)**:切面是AOP的核心,它结合了关注点(例如,日志记录)和它们的实现。在Spring AOP中,一个切面通常是一个包含通知(advisors)和...

    spring源码分析

    《Spring源码分析》 Spring框架作为Java领域中不可或缺的一部分,其强大之处在于它提供了丰富的功能,包括依赖注入(Dependency Injection,简称DI)、面向切面编程(Aspect-Oriented Programming,简称AOP)、事务...

    Spring5源码分析心得

    ### Spring5源码分析心得 #### 一、Spring框架中常用的设计模式 Spring框架作为一款优秀的Java企业级应用开发框架,其内部集成了多种设计模式,不仅有助于提高系统的可维护性和扩展性,还能够让开发者更好地理解和...

    spring源码包.zip

    通过对这些模块的源码分析,我们可以深入了解Spring如何实现其强大的功能,并能更好地运用到实际项目中,提升代码质量和可维护性。无论是新手还是经验丰富的开发者,理解Spring的源码都将是一次宝贵的进阶之旅。

    springaop:spring aop应用实例和源码解析

    在源码分析中,理解`AopProxy`、`TargetSource`以及它们如何协同工作以创建代理对象是关键。此外,`AspectJ`扩展了Spring AOP,提供了更强大的表达式语言和编译时织入,对复杂切面需求的开发者非常有用。 综上所述...

    二、Spring源码分析——BeanFactory

    《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...

    spring动态代理

    Spring 动态代理是 Spring 框架中的一个重要特性,它允许我们在运行时自动生成代理对象,以便在方法调用前后执行额外的操作,比如事务管理、AOP(面向切面编程)等。动态代理主要涉及两个核心接口:`java.lang....

    Spring2(源码)

    源码分析是理解Spring工作原理的关键,能帮助开发者深入掌握如何在实际项目中有效地使用和优化Spring。下面将对Spring框架的核心组件、设计理念以及源码中的关键部分进行详细的解释。 1. **依赖注入(DI)** - ...

    三、Spring源码分析——ApplicationContext

    《Spring源码分析——ApplicationContext》 在Java世界中,Spring框架是不可或缺的一部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,极大地...

    spring运行机制源码剖析

    通过深入源码分析,我们可以更好地理解Spring如何在幕后工作,从而更有效地利用这个强大的框架来构建复杂的企业级应用。希望这篇文章能帮助你提升对Spring的理解,让你在实际开发中更加得心应手。

    spring-orm源码

    当你看到TransactionProxyFactoryBean时,实际上是在创建一个事务增强的代理对象。源码中可以学习到AOP代理的工作原理,以及如何通过拦截器链执行事务逻辑。 7. **数据访问对象(DAO)支持** Spring-ORM提供了对...

    spring学习事务源码

    在源码分析中,我们可以看到当一个方法被@Transactional标记后,Spring会创建一个代理,这个代理在目标方法执行前后插入事务管理逻辑。在方法开始前,如果满足事务启动条件,就会调用`PlatformTransactionManager`的...

    spring源码剖析

    此外,Spring还支持基于接口的代理,例如,如果bean需要AOP代理,那么在从Map中获取bean之前,会先创建一个代理对象返回。 总的来说,Spring通过Bean Factory中的Map来管理和提供bean实例,这个机制使得对象的创建...

    spring源码

    而动态代理则在`spring-aop`模块中体现,如`JdkDynamicAopProxy`和`CglibAopProxy`用于创建代理对象。 另外,Spring的事件驱动模型(Event-driven model)和资源加载机制也是源码学习的重要部分。`ApplicationEvent...

    Spring底层学习:【AOP源码的探究】

    在本文中,我们将深入探讨Spring AOP的底层实现,特别是围绕`@EnableAspectJAutoProxy`注解和`AnnotationAwareAspectJAutoProxyCreator`组件的源码分析。 一、@EnableAspectJAutoProxy是什么? `@...

Global site tag (gtag.js) - Google Analytics