Spring AOP(2)代理类的创建ProxyFactoryBean

ProxyFactory

Spring IOC(9)里面介绍了三级缓存的时候,提到了AOP创建代理类的内容,有两个地方会去调用AbstractAutoProxyCreator.wrapIfNecessary()去创建代理类。

  1. 在解析wrapIfNecessary之前先看一下上面的图,分析一些基础的类:
  • Advised
    Advised要提供了Advice和Advisor的管理。
Advised
  • AdvisedSupport
    Advised的实现类,从代码里就能看出Advice会被封装成DefaultIntroductionAdvisor。
public void addAdvice(int pos, Advice advice) throws AopConfigException {
    Assert.notNull(advice, "Advice must not be null");
    if (advice instanceof IntroductionInfo) {
        // We don't need an IntroductionAdvisor for this kind of introduction:
        // It's fully self-describing.
        addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
    }
    else if (advice instanceof DynamicIntroductionAdvice) {
        // We need an IntroductionAdvisor for this kind of introduction.
        throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
    }
    else {
        addAdvisor(pos, new DefaultPointcutAdvisor(advice));
    }
}
private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
    Assert.notNull(advisor, "Advisor must not be null");
    if (isFrozen()) {
        throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
    }
    if (pos > this.advisors.size()) {
        throw new IllegalArgumentException(
                "Illegal position " + pos + " in advisor list with size " + this.advisors.size());
    }
    this.advisors.add(pos, advisor);
    updateAdvisorArray();
    adviceChanged();
}
  • ProxyCreatorSupport
    实现了AdvisedSupport,同时定义了AopProxyFactory的成员变量(默认实现DefaultAopProxyFactory),所以ProxyCreatorSupport提供了通过AopProxy获得proxy的能力。
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.");
        }
        //如果目标类是有实现接口的,或者targetClass是由Proxy创建的(JDK代理)
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        //否则通过Cglib方式创建动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}
  • ProxyFactory
    在ProxyCreatorSupport提供了获取AopProxy能力之后,ProxyFactory就提供通过AopProxy获取Proxy实例的能力createAopProxy().getProxy()。


    ProxyFactory
  • ProxyFactoryBean
    ProxyFactoryBean不仅仅继承了ProxyCreatorSupport也有获得Proxy的能力,另外ProxyFactoryBean还实现了FactoryBean(FactoryBean的注意事项,FactoryBean在通过getBean()生成实例的时候,是默认调用getObject()创建需要的bean,如果想要FactoryBean本身的实例,需要加上&符号),所以这里默认调用getObject()方法来创建proxy对象。

  1. 正确的使用ProxyFactoryBean:
<bean id="subject" class="com.gary.spring.proxy.RealSubject" />
<bean id="testAdvice" class="com.gary.spring.proxy.TestAdvice" />
<bean id="subjectProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
    <property name="proxyInterfaces">
        <value>com.gary.spring.proxy.Subject</value>
    </property>
    <property name="interceptorNames">
        <list>
            <value>testAdvice</value>
        </list>
    </property>
    <property name="target">
        <ref bean="subject"/>
    </property>
</bean>
//这里直接通过getBean获取ProxyFactoryBean的实例,会默认调用getObject()方法生成代理对象
Subject subject = (Subject) beanFactory.getBean("subjectProxy");
subject.sayName();

这里面声明了三个bean,一个真实对象RealSubject,一个Advice,还有一个ProxyFactoryBean。
三个bean创建的时机是不一样的,测试main通过getBean()创建subjectProxy,在populateBean的时候,会去创建subject对应的bean,而testAdvice是在initializeAdvisorChain的过程中通过getBean()进行实例化。

  1. ProxyFactoryBean生成Proxy代码解析
  • FactoryBean.getObject()代码
public Object getObject() throws BeansException {
    //调用initializeAdvisorChain来初始化Advisor
    initializeAdvisorChain();
    if (isSingleton()) {
        return getSingletonInstance();
    }
    else {
        if (this.targetName == null) {
            logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
                    "Enable prototype proxies by setting the 'targetName' property.");
        }
        return newPrototypeInstance();
    }
}   
  • initializeAdvisorChain解析:
    这里主要涉及Advice实例的创建,如果是单例的,就通过this.beanFactory.getBean(name)创建Advice实例。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
    //在xml里面设置了interceptorNames
    if (!ObjectUtils.isEmpty(this.interceptorNames)) {
        //所以这里会遍历interceptorNames,创建所需要的Advisor
        // Materialize interceptor chain from bean names.
        for (String name : this.interceptorNames) {
            //处理全局的Advisor
            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()));
            }
            //处理对应的Advisor
            else {
                // If we get here, we need to add a named interceptor.
                // We must check if it's a singleton or prototype.
                Object advice;
                if (this.singleton || this.beanFactory.isSingleton(name)) {
                    // Add the real Advisor/Advice to the chain.
                    //如果是单例的,就通过getBane(beanName)获得Advice
                    advice = this.beanFactory.getBean(name);
                }
                else {
                    // It's a prototype Advice or Advisor: replace with a prototype.
                    // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                    //否则就通过property方式创建Advisor
                    advice = new PrototypePlaceholderAdvisor(name);
                }
                //将Advice,Advisor或者object添加到interceptor 列表
                addAdvisorOnChainCreation(advice, name);
            }
        }
    }

    this.advisorChainInitialized = true;
}
  • 创建完Advice实例之后,调用addAdvisorOnChainCreation将Advice转换成Advisor。
    advisorAdapterRegistry默认是DefaultAdvisorAdapterRegistry。

//将Advice,Advisor或者object添加到interceptor 列表
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);
}
//通过advisorAdapterRegistry将Advice转换或者wrapper成Advisor
private Advisor namedBeanToAdvisor(Object next) {
    try {
        return this.advisorAdapterRegistry.wrap(next);
    }
    catch (UnknownAdviceTypeException ex) {
        // We expected this to be an Advisor or Advice,
        // but it wasn't. This is a configuration error.
        throw new AopConfigException("Unknown advisor type " + next.getClass() +
                "; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry," +
                "which may also be target or TargetSource", ex);
    }
}
//将Advice包装wrapper成Advisor
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    //如果adviceObject就是Advisor,就直接返回,不需要包装
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    //如果adviceObject不是Advice类型,就报错,因为MethodInteceptor也是Advice的子类
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    //如果是MethodInteceptor,就直接包装成DefaultPointcutAdvisor
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    //如果是正常的Advice实现,就需要通过adapters来验证是不是支持该Advice
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}
  • Advisor都加载好之后,调用getSingletonInstance来创建代理类。
    需要注意的是JdkDynamicAopProxy内部有AdvisedSupport advised成员变量,所以在通过ProxyCreatorSupport构建JdkDynamicAopProxy的时候需要传入this,因为ProxyCreatorSupport继承自AdvisedSupport。
    AdvisedSupport内部有List<Advisor> advisors,所以Advice以及Advisor都会被转化成Advisor保存在该list内部。
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);
        //调用ProxyCreatorSupport.createAopProxy()来获取AopProxy,再通过AopProxy获取Proxy实例
        this.singletonInstance = getProxy(createAopProxy());
    }
    return this.singletonInstance;
}
//父类ProxyCreatorSupport.createAopProxy()创建AopProxy
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
     //注意这里是将this传入,即AdvisedSupport实例
    return getAopProxyFactory().createAopProxy(this);
}
protected Object getProxy(AopProxy aopProxy) {
    return aopProxy.getProxy(this.proxyClassLoader);
}

再回顾一下FactoryBean的getObject流程:
正常beanFactory.getBean("subjectProxy")创建的是ProxyFactoryBean,在populateBean的过程中,创建subject的实例,在这之后会调用getObjectForBeanInstance()方法,这里面就是Bean和FactoryBean的区别之处:

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    //isFactoryDereference会检查beanName是不是&打头的,如果是,就直接返回FactoryBean实例,而不是getObject()生成的实例
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    //  如果不是FactoryBean,就直接返回
    // 或者isFactoryDereference,即beanName是&打头的,也就直接返回bean
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }
    //如果是FactoryBean,就通过getObject()方法,返回真正需要的实例对象
    Object object = null;
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

上述流程简述了利用ProxyFactoryBean来创建代理对象的过程,通过XML来演示会比较直白,下面就通过spring aop配置看看是如何创建代理对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容